initial commit for version 1.5.x patch release
[OpenFOAM-1.5.x.git] / src / OpenFOAM / fields / FieldFields / FieldField / FieldFieldFunctions.C
blobce95f7add7930ed3b37ba9dae7a30f4db05d2d4d
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2008 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         WarningIn("max(const FieldField<Field, Type>&) const")
434             << "empty fieldField, returning zero" << endl;
436         return pTraits<Type>::zero;
437     }
440 TMP_UNARY_FUNCTION(Type, max)
442 template<template<class> class Field, class Type>
443 Type min(const FieldField<Field, Type>& f)
445     label i = 0;
446     while(i < f.size() && !f[i].size()) i++;
448     if (i < f.size())
449     {
450         label i = 0;
451         while(!f[i].size()) i++;
453         Type Min(min(f[i]));
455         for (label j=i+1; j<f.size(); j++)
456         {
457             if (f[j].size())
458             {
459                 Min = min(min(f[j]), Min);
460             }
461         }
463         return Min;
464     }
465     else
466     {
467         WarningIn("min(const FieldField<Field, Type>&) const")
468             << "empty fieldField, returning zero" << endl;
470         return pTraits<Type>::zero;
471     }
474 TMP_UNARY_FUNCTION(Type, min)
476 template<template<class> class Field, class Type>
477 Type sum(const FieldField<Field, Type>& f)
479     if (f.size())
480     {
481         Type Sum = pTraits<Type>::zero;
483         forAll(f, i)
484         {
485             Sum += sum(f[i]);
486         }
488         return Sum;
489     }
490     else
491     {
492         return pTraits<Type>::zero;
493     }
496 TMP_UNARY_FUNCTION(Type, sum)
498 template<template<class> class Field, class Type>
499 scalar sumMag(const FieldField<Field, Type>& f)
501     if (f.size())
502     {
503         scalar SumMag = 0.0;
505         forAll(f, i)
506         {
507             SumMag += sumMag(f[i]);
508         }
510         return SumMag;
511     }
512     else
513     {
514         return 0.0;
515     }
518 TMP_UNARY_FUNCTION(scalar, sumMag)
520 template<template<class> class Field, class Type>
521 Type average(const FieldField<Field, Type>& f)
523     if (f.size())
524     {
525         label n = 0;
527         forAll(f, i)
528         {
529             n += f[i].size();
530         }
532         if (n == 0)
533         {
534             WarningIn("average(const FieldField<Field, Type>&) const")
535                 << "empty fieldField, returning zero" << endl;
537             return pTraits<Type>::zero;
538         }
540         Type avrg = sum(f)/n;
542         return avrg;
543     }
544     else
545     {
546         WarningIn("average(const FieldField<Field, Type>&) const")
547             << "empty fieldField, returning zero" << endl;
549         return pTraits<Type>::zero;
550     }
553 TMP_UNARY_FUNCTION(Type, average)
556 #include "PstreamReduceOps.H"
558 #define G_UNARY_FUNCTION(returnType, gFunc, func, rFunc)                      \
559                                                                               \
560 template<template<class> class Field, class Type>                             \
561 returnType gFunc(const FieldField<Field, Type>& f)                            \
562 {                                                                             \
563     returnType res = func(f);                                                 \
564     reduce(res, rFunc##Op<Type>());                                           \
565     return res;                                                               \
566 }                                                                             \
567 TMP_UNARY_FUNCTION(returnType, gFunc)
569 G_UNARY_FUNCTION(Type, gMax, max, max)
570 G_UNARY_FUNCTION(Type, gMin, min, min)
571 G_UNARY_FUNCTION(Type, gSum, sum, sum)
572 G_UNARY_FUNCTION(scalar, gSumMag, sumMag, sum)
574 #undef G_UNARY_FUNCTION
577 template<template<class> class Field, class Type>
578 Type gAverage(const FieldField<Field, Type>& f)
580     label n = 0;
582     forAll(f, i)
583     {
584         n += f[i].size();
585     }
587     reduce(n, sumOp<label>());
589     if (n > 0)
590     {
591         Type avrg = gSum(f)/n;
593         return avrg;
594     }
595     else
596     {
597         WarningIn("gAverage(const FieldField<Field, Type>&) const")
598             << "empty fieldField, returning zero" << endl;
600         return pTraits<Type>::zero;
601     }
604 TMP_UNARY_FUNCTION(Type, gAverage)
606 #undef TMP_UNARY_FUNCTION
609 BINARY_FUNCTION(Type, Type, Type, max)
610 BINARY_FUNCTION(Type, Type, Type, min)
611 BINARY_FUNCTION(Type, Type, Type, cmptMultiply)
612 BINARY_FUNCTION(Type, Type, Type, cmptDivide)
614 BINARY_TYPE_FUNCTION(Type, Type, Type, max)
615 BINARY_TYPE_FUNCTION(Type, Type, Type, min)
616 BINARY_TYPE_FUNCTION(Type, Type, Type, cmptMultiply)
617 BINARY_TYPE_FUNCTION(Type, Type, Type, cmptDivide)
620 /* * * * * * * * * * * * * * * * Global operators  * * * * * * * * * * * * * */
622 UNARY_OPERATOR(Type, Type, -, negate)
624 #ifndef __INTEL_COMPILER
625 BINARY_OPERATOR(Type, Type, scalar, *, multiply)
626 BINARY_OPERATOR(Type, scalar, Type, *, multiply)
627 #endif
628 BINARY_OPERATOR(Type, Type, scalar, /, divide)
630 BINARY_TYPE_OPERATOR_SF(Type, scalar, Type, *, multiply)
631 BINARY_TYPE_OPERATOR_FS(Type, Type, scalar, *, multiply)
633 BINARY_TYPE_OPERATOR_FS(Type, Type, scalar, /, divide)
636 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
638 #define PRODUCT_OPERATOR(product, op, opFunc)                                 \
639                                                                               \
640 template<template<class> class Field, class Type1, class Type2>               \
641 void opFunc                                                                   \
642 (                                                                             \
643     FieldField<Field, typename product<Type1, Type2>::type>& f,               \
644     const FieldField<Field, Type1>& f1,                                       \
645     const FieldField<Field, Type2>& f2                                        \
646 )                                                                             \
647 {                                                                             \
648     forAll(f, i)                                                              \
649     {                                                                         \
650         opFunc(f[i], f1[i], f2[i]);                                           \
651     }                                                                         \
652 }                                                                             \
653                                                                               \
654 template<template<class> class Field, class Type1, class Type2>               \
655 tmp<FieldField<Field, typename product<Type1, Type2>::type> >                 \
656 operator op                                                                   \
657 (                                                                             \
658     const FieldField<Field, Type1>& f1,                                       \
659     const FieldField<Field, Type2>& f2                                        \
660 )                                                                             \
661 {                                                                             \
662     typedef typename product<Type1, Type2>::type productType;                 \
663     tmp<FieldField<Field, productType> > tRes                                 \
664     (                                                                         \
665         FieldField<Field, productType>::NewCalculatedType(f1)                 \
666     );                                                                        \
667     opFunc(tRes(), f1, f2);                                                   \
668     return tRes;                                                              \
669 }                                                                             \
670                                                                               \
671 template<template<class> class Field, class Type1, class Type2>               \
672 tmp<FieldField<Field, typename product<Type1, Type2>::type> >                 \
673 operator op                                                                   \
674 (                                                                             \
675     const FieldField<Field, Type1>& f1,                                       \
676     const tmp<FieldField<Field, Type2> >& tf2                                 \
677 )                                                                             \
678 {                                                                             \
679     typedef typename product<Type1, Type2>::type productType;                 \
680     tmp<FieldField<Field, productType> > tRes                                 \
681     (                                                                         \
682         reuseTmpFieldField<Field, productType, Type2>::New(tf2)               \
683     );                                                                        \
684     opFunc(tRes(), f1, tf2());                                                \
685     reuseTmpFieldField<Field, productType, Type2>::clear(tf2);                \
686     return tRes;                                                              \
687 }                                                                             \
688                                                                               \
689 template<template<class> class Field, class Type1, class Type2>               \
690 tmp<FieldField<Field, typename product<Type1, Type2>::type> >                 \
691 operator op                                                                   \
692 (                                                                             \
693     const tmp<FieldField<Field, Type1> >& tf1,                                \
694     const FieldField<Field, Type2>& f2                                        \
695 )                                                                             \
696 {                                                                             \
697     typedef typename product<Type1, Type2>::type productType;                 \
698     tmp<FieldField<Field, productType> > tRes                                 \
699     (                                                                         \
700         reuseTmpFieldField<Field, productType, Type1>::New(tf1)               \
701     );                                                                        \
702     opFunc(tRes(), tf1(), f2);                                                \
703     reuseTmpFieldField<Field, productType, Type1>::clear(tf1);                \
704     return tRes;                                                              \
705 }                                                                             \
706                                                                               \
707 template<template<class> class Field, class Type1, class Type2>               \
708 tmp<FieldField<Field, typename product<Type1, Type2>::type> >                 \
709 operator op                                                                   \
710 (                                                                             \
711     const tmp<FieldField<Field, Type1> >& tf1,                                \
712     const tmp<FieldField<Field, Type2> >& tf2                                 \
713 )                                                                             \
714 {                                                                             \
715     typedef typename product<Type1, Type2>::type productType;                 \
716     tmp<FieldField<Field, productType> > tRes                                 \
717     (                                                                         \
718         reuseTmpTmpFieldField<Field, productType, Type1, Type1, Type2>::New   \
719             (tf1, tf2)                                                        \
720     );                                                                        \
721     opFunc(tRes(), tf1(), tf2());                                             \
722     reuseTmpTmpFieldField<Field, productType, Type1, Type1, Type2>::clear     \
723         (tf1, tf2);                                                           \
724     return tRes;                                                              \
725 }                                                                             \
726                                                                               \
727 template                                                                      \
728 <template<class> class Field, class Type, class Form, class Cmpt, int nCmpt>  \
729 void opFunc                                                                   \
730 (                                                                             \
731     FieldField<Field, typename product<Type, Form>::type>& f,                 \
732     const FieldField<Field, Type>& f1,                                        \
733     const VectorSpace<Form,Cmpt,nCmpt>& vs                                    \
734 )                                                                             \
735 {                                                                             \
736     forAll(f, i)                                                              \
737     {                                                                         \
738         opFunc(f[i], f1[i], vs);                                              \
739     }                                                                         \
740 }                                                                             \
741                                                                               \
742 template                                                                      \
743 <template<class> class Field, class Type, class Form, class Cmpt, int nCmpt>  \
744 tmp<FieldField<Field, typename product<Type, Form>::type> >                   \
745 operator op                                                                   \
746 (                                                                             \
747     const FieldField<Field, Type>& f1,                                        \
748     const VectorSpace<Form,Cmpt,nCmpt>& vs                                    \
749 )                                                                             \
750 {                                                                             \
751     typedef typename product<Type, Form>::type productType;                   \
752     tmp<FieldField<Field, productType> > tRes                                 \
753     (                                                                         \
754         FieldField<Field, productType>::NewCalculatedType(f1)                 \
755     );                                                                        \
756     opFunc(tRes(), f1, static_cast<const Form&>(vs));                         \
757     return tRes;                                                              \
758 }                                                                             \
759                                                                               \
760 template                                                                      \
761 <template<class> class Field, class Type, class Form, class Cmpt, int nCmpt>  \
762 tmp<FieldField<Field, typename product<Type, Form>::type> >                   \
763 operator op                                                                   \
764 (                                                                             \
765     const tmp<FieldField<Field, Type> >& tf1,                                 \
766     const VectorSpace<Form,Cmpt,nCmpt>& vs                                    \
767 )                                                                             \
768 {                                                                             \
769     typedef typename product<Type, Form>::type productType;                   \
770     tmp<FieldField<Field, productType> > tRes                                 \
771     (                                                                         \
772         reuseTmpFieldField<Field, productType, Type>::New(tf1)                \
773     );                                                                        \
774     opFunc(tRes(), tf1(), static_cast<const Form&>(vs));                      \
775     reuseTmpFieldField<Field, productType, Type>::clear(tf1);                 \
776     return tRes;                                                              \
777 }                                                                             \
778                                                                               \
779 template                                                                      \
780 <template<class> class Field, class Form, class Cmpt, int nCmpt, class Type>  \
781 void opFunc                                                                   \
782 (                                                                             \
783     FieldField<Field, typename product<Form, Type>::type>& f,                 \
784     const VectorSpace<Form,Cmpt,nCmpt>& vs,                                   \
785     const FieldField<Field, Type>& f1                                         \
786 )                                                                             \
787 {                                                                             \
788     forAll(f, i)                                                              \
789     {                                                                         \
790         opFunc(f[i], vs, f1[i]);                                              \
791     }                                                                         \
792 }                                                                             \
793                                                                               \
794 template                                                                      \
795 <template<class> class Field, class Form, class Cmpt, int nCmpt, class Type>  \
796 tmp<FieldField<Field, typename product<Form, Type>::type> >                   \
797 operator op                                                                   \
798 (                                                                             \
799     const VectorSpace<Form,Cmpt,nCmpt>& vs,                                   \
800     const FieldField<Field, Type>& f1                                         \
801 )                                                                             \
802 {                                                                             \
803     typedef typename product<Form, Type>::type productType;                   \
804     tmp<FieldField<Field, productType> > tRes                                 \
805     (                                                                         \
806         FieldField<Field, productType>::NewCalculatedType(f1)                 \
807     );                                                                        \
808     opFunc(tRes(), static_cast<const Form&>(vs), f1);                         \
809     return tRes;                                                              \
810 }                                                                             \
811                                                                               \
812 template                                                                      \
813 <template<class> class Field, class Form, class Cmpt, int nCmpt, class Type>  \
814 tmp<FieldField<Field, typename product<Form, Type>::type> >                   \
815 operator op                                                                   \
816 (                                                                             \
817     const VectorSpace<Form,Cmpt,nCmpt>& vs,                                   \
818     const tmp<FieldField<Field, Type> >& tf1                                  \
819 )                                                                             \
820 {                                                                             \
821     typedef typename product<Form, Type>::type productType;                   \
822     tmp<FieldField<Field, productType> > tRes                                 \
823     (                                                                         \
824         reuseTmpFieldField<Field, productType, Type>::New(tf1)                \
825     );                                                                        \
826     opFunc(tRes(), static_cast<const Form&>(vs), tf1());                      \
827     reuseTmpFieldField<Field, productType, Type>::clear(tf1);                 \
828     return tRes;                                                              \
831 PRODUCT_OPERATOR(typeOfSum, +, add)
832 PRODUCT_OPERATOR(typeOfSum, -, subtract)
834 PRODUCT_OPERATOR(outerProduct, *, outer)
835 PRODUCT_OPERATOR(crossProduct, ^, cross)
836 PRODUCT_OPERATOR(innerProduct, &, dot)
837 PRODUCT_OPERATOR(scalarProduct, &&, dotdot)
839 #undef PRODUCT_OPERATOR
842 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
844 } // End namespace Foam
846 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
848 #include "undefFieldFunctionsM.H"
850 // ************************************************************************* //