/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\/ M anipulation | Copyright (C) 2018-2019 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "GeometricFieldReuseFunctions.H" #define TEMPLATE \ template class PatchField, class GeoMesh> #include "GeometricFieldFunctionsM.C" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { // * * * * * * * * * * * * * * * Global functions * * * * * * * * * * * * * // template class PatchField, class GeoMesh> void component ( GeometricField < typename GeometricField::cmptType, PatchField, GeoMesh >& gcf, const GeometricField& gf, const direction d ) { component(gcf.primitiveFieldRef(), gf.primitiveField(), d); component(gcf.boundaryFieldRef(), gf.boundaryField(), d); gcf.oriented() = gf.oriented(); } template class PatchField, class GeoMesh> void T ( GeometricField& gf, const GeometricField& gf1 ) { T(gf.primitiveFieldRef(), gf1.primitiveField()); T(gf.boundaryFieldRef(), gf1.boundaryField()); gf.oriented() = gf1.oriented(); } template < class Type, template class PatchField, class GeoMesh, direction r > void pow ( GeometricField::type, PatchField, GeoMesh>& gf, const GeometricField& gf1 ) { pow(gf.primitiveFieldRef(), gf1.primitiveField(), r); pow(gf.boundaryFieldRef(), gf1.boundaryField(), r); gf.oriented() = pow(gf1.oriented(), r); } template < class Type, template class PatchField, class GeoMesh, direction r > tmp::type, PatchField, GeoMesh>> pow ( const GeometricField& gf, typename powProduct::type ) { typedef typename powProduct::type powProductType; auto tres = tmp>::New ( IOobject ( "pow(" + gf.name() + ',' + name(r) + ')', gf.instance(), gf.db(), IOobject::NO_READ, IOobject::NO_WRITE ), gf.mesh(), pow(gf.dimensions(), r) ); pow(tres.ref(), gf); return tres; } template < class Type, template class PatchField, class GeoMesh, direction r > tmp::type, PatchField, GeoMesh>> pow ( const tmp>& tgf, typename powProduct::type ) { typedef typename powProduct::type powProductType; const GeometricField& gf = tgf(); auto tres = tmp>::New ( IOobject ( "pow(" + gf.name() + ',' + name(r) + ')', gf.instance(), gf.db(), IOobject::NO_READ, IOobject::NO_WRITE ), gf.mesh(), pow(gf.dimensions(), r) ); pow(tres.ref(), gf); tgf.clear(); return tres; } template class PatchField, class GeoMesh> void sqr ( GeometricField ::type, PatchField, GeoMesh>& gf, const GeometricField& gf1 ) { sqr(gf.primitiveFieldRef(), gf1.primitiveField()); sqr(gf.boundaryFieldRef(), gf1.boundaryField()); gf.oriented() = sqr(gf1.oriented()); } template class PatchField, class GeoMesh> tmp < GeometricField < typename outerProduct::type, PatchField, GeoMesh > > sqr(const GeometricField& gf) { typedef typename outerProduct::type outerProductType; auto tres = tmp>::New ( IOobject ( "sqr(" + gf.name() + ')', gf.instance(), gf.db(), IOobject::NO_READ, IOobject::NO_WRITE ), gf.mesh(), sqr(gf.dimensions()) ); sqr(tres.ref(), gf); return tres; } template class PatchField, class GeoMesh> tmp < GeometricField < typename outerProduct::type, PatchField, GeoMesh > > sqr(const tmp>& tgf) { typedef typename outerProduct::type outerProductType; const GeometricField& gf = tgf(); auto tres = tmp>::New ( IOobject ( "sqr(" + gf.name() + ')', gf.instance(), gf.db(), IOobject::NO_READ, IOobject::NO_WRITE ), gf.mesh(), sqr(gf.dimensions()) ); sqr(tres.ref(), gf); tgf.clear(); return tres; } template class PatchField, class GeoMesh> void magSqr ( GeometricField& gsf, const GeometricField& gf ) { magSqr(gsf.primitiveFieldRef(), gf.primitiveField()); magSqr(gsf.boundaryFieldRef(), gf.boundaryField()); gsf.oriented() = magSqr(gf.oriented()); } template class PatchField, class GeoMesh> tmp> magSqr ( const GeometricField& gf ) { auto tres = tmp>::New ( IOobject ( "magSqr(" + gf.name() + ')', gf.instance(), gf.db(), IOobject::NO_READ, IOobject::NO_WRITE ), gf.mesh(), sqr(gf.dimensions()) ); magSqr(tres.ref(), gf); return tres; } template class PatchField, class GeoMesh> tmp> magSqr ( const tmp>& tgf ) { const GeometricField& gf = tgf(); auto tres = tmp>::New ( IOobject ( "magSqr(" + gf.name() + ')', gf.instance(), gf.db(), IOobject::NO_READ, IOobject::NO_WRITE ), gf.mesh(), sqr(gf.dimensions()) ); magSqr(tres.ref(), gf); tgf.clear(); return tres; } template class PatchField, class GeoMesh> void mag ( GeometricField& gsf, const GeometricField& gf ) { mag(gsf.primitiveFieldRef(), gf.primitiveField()); mag(gsf.boundaryFieldRef(), gf.boundaryField()); gsf.oriented() = mag(gf.oriented()); } template class PatchField, class GeoMesh> tmp> mag ( const GeometricField& gf ) { auto tres = tmp>::New ( IOobject ( "mag(" + gf.name() + ')', gf.instance(), gf.db(), IOobject::NO_READ, IOobject::NO_WRITE ), gf.mesh(), gf.dimensions() ); mag(tres.ref(), gf); return tres; } template class PatchField, class GeoMesh> tmp> mag ( const tmp>& tgf ) { const GeometricField& gf = tgf(); auto tres = tmp>::New ( IOobject ( "mag(" + gf.name() + ')', gf.instance(), gf.db(), IOobject::NO_READ, IOobject::NO_WRITE ), gf.mesh(), gf.dimensions() ); mag(tres.ref(), gf); tgf.clear(); return tres; } template class PatchField, class GeoMesh> void cmptAv ( GeometricField < typename GeometricField::cmptType, PatchField, GeoMesh >& gcf, const GeometricField& gf ) { cmptAv(gcf.primitiveFieldRef(), gf.primitiveField()); cmptAv(gcf.boundaryFieldRef(), gf.boundaryField()); gcf.oriented() = cmptAv(gf.oriented()); } template class PatchField, class GeoMesh> tmp < GeometricField < typename GeometricField::cmptType, PatchField, GeoMesh > > cmptAv(const GeometricField& gf) { typedef typename GeometricField::cmptType cmptType; auto tres = tmp>::New ( IOobject ( "cmptAv(" + gf.name() + ')', gf.instance(), gf.db(), IOobject::NO_READ, IOobject::NO_WRITE ), gf.mesh(), gf.dimensions() ); cmptAv(tres.ref(), gf); return tres; } template class PatchField, class GeoMesh> tmp < GeometricField < typename GeometricField::cmptType, PatchField, GeoMesh > > cmptAv(const tmp>& tgf) { typedef typename GeometricField::cmptType cmptType; const GeometricField& gf = tgf(); auto tres = tmp>::New ( IOobject ( "cmptAv(" + gf.name() + ')', gf.instance(), gf.db(), IOobject::NO_READ, IOobject::NO_WRITE ), gf.mesh(), gf.dimensions() ); cmptAv(tres.ref(), gf); tgf.clear(); return tres; } #define UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(returnType, func, binaryOp) \ \ template class PatchField, class GeoMesh> \ dimensioned func \ ( \ const GeometricField& gf \ ) \ { \ return dimensioned \ ( \ #func "(" + gf.name() + ')', \ gf.dimensions(), \ returnReduce \ ( \ Foam::func \ ( \ Foam::func(gf.primitiveField()), \ Foam::func(gf.boundaryField()) \ ), \ binaryOp() \ ) \ ); \ } \ \ template class PatchField, class GeoMesh> \ dimensioned func \ ( \ const tmp>& tgf1 \ ) \ { \ dimensioned res = func(tgf1()); \ tgf1.clear(); \ return res; \ } UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(Type, max, maxOp) UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(Type, min, minOp) UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(MinMax, minMax, minMaxOp) UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY(scalarMinMax, minMaxMag, minMaxMagOp) #undef UNARY_REDUCTION_FUNCTION_WITH_BOUNDARY #define UNARY_REDUCTION_FUNCTION(returnType, func, gFunc) \ \ template class PatchField, class GeoMesh> \ dimensioned func \ ( \ const GeometricField& gf \ ) \ { \ return dimensioned \ ( \ #func "(" + gf.name() + ')', \ gf.dimensions(), \ gFunc(gf.primitiveField()) \ ); \ } \ \ template class PatchField, class GeoMesh> \ dimensioned func \ ( \ const tmp>& tgf1 \ ) \ { \ dimensioned res = func(tgf1()); \ tgf1.clear(); \ return res; \ } UNARY_REDUCTION_FUNCTION(Type, sum, gSum) UNARY_REDUCTION_FUNCTION(scalar, sumMag, gSumMag) UNARY_REDUCTION_FUNCTION(Type, average, gAverage) #undef UNARY_REDUCTION_FUNCTION BINARY_FUNCTION(Type, Type, Type, max) BINARY_FUNCTION(Type, Type, Type, min) BINARY_FUNCTION(Type, Type, Type, cmptMultiply) BINARY_FUNCTION(Type, Type, Type, cmptDivide) BINARY_TYPE_FUNCTION(Type, Type, Type, max) BINARY_TYPE_FUNCTION(Type, Type, Type, min) BINARY_TYPE_FUNCTION(Type, Type, Type, cmptMultiply) BINARY_TYPE_FUNCTION(Type, Type, Type, cmptDivide) // * * * * * * * * * * * * * * * Global operators * * * * * * * * * * * * * // UNARY_OPERATOR(Type, Type, -, negate, transform) BINARY_OPERATOR(Type, Type, scalar, *, '*', multiply) BINARY_OPERATOR(Type, scalar, Type, *, '*', multiply) BINARY_OPERATOR(Type, Type, scalar, /, '|', divide) BINARY_TYPE_OPERATOR_SF(Type, scalar, Type, *, '*', multiply) BINARY_TYPE_OPERATOR_FS(Type, Type, scalar, *, '*', multiply) BINARY_TYPE_OPERATOR_FS(Type, Type, scalar, /, '|', divide) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #define PRODUCT_OPERATOR(product, op, opFunc) \ \ template \ class PatchField, class GeoMesh> \ void opFunc \ ( \ GeometricField \ ::type, PatchField, GeoMesh>& gf, \ const GeometricField& gf1, \ const GeometricField& gf2 \ ) \ { \ Foam::opFunc \ ( \ gf.primitiveFieldRef(), \ gf1.primitiveField(), \ gf2.primitiveField() \ ); \ Foam::opFunc \ ( \ gf.boundaryFieldRef(), \ gf1.boundaryField(), \ gf2.boundaryField() \ ); \ \ gf.oriented() = gf1.oriented() op gf2.oriented(); \ } \ \ template \ class PatchField, class GeoMesh> \ tmp \ < \ GeometricField::type, PatchField, GeoMesh> \ > \ operator op \ ( \ const GeometricField& gf1, \ const GeometricField& gf2 \ ) \ { \ typedef typename product::type productType; \ \ auto tres = \ tmp>::New \ ( \ IOobject \ ( \ '(' + gf1.name() + #op + gf2.name() + ')', \ gf1.instance(), \ gf1.db(), \ IOobject::NO_READ, \ IOobject::NO_WRITE \ ), \ gf1.mesh(), \ gf1.dimensions() op gf2.dimensions() \ ); \ \ Foam::opFunc(tres.ref(), gf1, gf2); \ \ return tres; \ } \ \ \ template \ class PatchField, class GeoMesh> \ tmp \ < \ GeometricField::type, PatchField, GeoMesh> \ > \ operator op \ ( \ const GeometricField& gf1, \ const tmp>& tgf2 \ ) \ { \ typedef typename product::type productType; \ \ const GeometricField& gf2 = tgf2(); \ \ auto tres = \ reuseTmpGeometricField::New \ ( \ tgf2, \ '(' + gf1.name() + #op + gf2.name() + ')', \ gf1.dimensions() op gf2.dimensions() \ ); \ \ Foam::opFunc(tres.ref(), gf1, gf2); \ \ tgf2.clear(); \ \ return tres; \ } \ \ template \ class PatchField, class GeoMesh> \ tmp \ < \ GeometricField::type, PatchField, GeoMesh> \ > \ operator op \ ( \ const tmp>& tgf1, \ const GeometricField& gf2 \ ) \ { \ typedef typename product::type productType; \ \ const GeometricField& gf1 = tgf1(); \ \ auto tres = \ reuseTmpGeometricField::New \ ( \ tgf1, \ '(' + gf1.name() + #op + gf2.name() + ')', \ gf1.dimensions() op gf2.dimensions() \ ); \ \ Foam::opFunc(tres.ref(), gf1, gf2); \ \ tgf1.clear(); \ \ return tres; \ } \ \ template \ class PatchField, class GeoMesh> \ tmp \ < \ GeometricField::type, PatchField, GeoMesh> \ > \ operator op \ ( \ const tmp>& tgf1, \ const tmp>& tgf2 \ ) \ { \ typedef typename product::type productType; \ \ const GeometricField& gf1 = tgf1(); \ const GeometricField& gf2 = tgf2(); \ \ auto tres = \ reuseTmpTmpGeometricField \ ::New \ ( \ tgf1, \ tgf2, \ '(' + gf1.name() + #op + gf2.name() + ')', \ gf1.dimensions() op gf2.dimensions() \ ); \ \ Foam::opFunc(tres.ref(), gf1, gf2); \ \ tgf1.clear(); \ tgf2.clear(); \ \ return tres; \ } \ \ template \ class PatchField, class GeoMesh> \ void opFunc \ ( \ GeometricField \ ::type, PatchField, GeoMesh>& gf, \ const GeometricField& gf1, \ const dimensioned
& dvs \ ) \ { \ Foam::opFunc(gf.primitiveFieldRef(), gf1.primitiveField(), dvs.value()); \ Foam::opFunc(gf.boundaryFieldRef(), gf1.boundaryField(), dvs.value()); \ gf.oriented() = gf1.oriented(); \ } \ \ template \ class PatchField, class GeoMesh> \ tmp::type, PatchField, GeoMesh>> \ operator op \ ( \ const GeometricField& gf1, \ const dimensioned& dvs \ ) \ { \ typedef typename product::type productType; \ \ auto tres = \ tmp>::New \ ( \ IOobject \ ( \ '(' + gf1.name() + #op + dvs.name() + ')', \ gf1.instance(), \ gf1.db(), \ IOobject::NO_READ, \ IOobject::NO_WRITE \ ), \ gf1.mesh(), \ gf1.dimensions() op dvs.dimensions() \ ); \ \ Foam::opFunc(tres.ref(), gf1, dvs); \ \ return tres; \ } \ \ template \ < \ class Form, \ class Cmpt, \ direction nCmpt, \ class Type, template class PatchField, \ class GeoMesh \ > \ tmp::type, PatchField, GeoMesh>> \ operator op \ ( \ const GeometricField& gf1, \ const VectorSpace& vs \ ) \ { \ return gf1 op dimensioned(static_cast(vs)); \ } \ \ \ template \ class PatchField, class GeoMesh> \ tmp::type, PatchField, GeoMesh>> \ operator op \ ( \ const tmp>& tgf1, \ const dimensioned& dvs \ ) \ { \ typedef typename product::type productType; \ \ const GeometricField& gf1 = tgf1(); \ \ auto tres = \ reuseTmpGeometricField::New \ ( \ tgf1, \ '(' + gf1.name() + #op + dvs.name() + ')', \ gf1.dimensions() op dvs.dimensions() \ ); \ \ Foam::opFunc(tres.ref(), gf1, dvs); \ \ tgf1.clear(); \ \ return tres; \ } \ \ template \ < \ class Form, \ class Cmpt, \ direction nCmpt, \ class Type, template class PatchField, \ class GeoMesh \ > \ tmp::type, PatchField, GeoMesh>> \ operator op \ ( \ const tmp>& tgf1, \ const VectorSpace& vs \ ) \ { \ return tgf1 op dimensioned(static_cast(vs)); \ } \ \ \ template \ class PatchField, class GeoMesh> \ void opFunc \ ( \ GeometricField \ ::type, PatchField, GeoMesh>& gf, \ const dimensioned& dvs, \ const GeometricField& gf1 \ ) \ { \ Foam::opFunc(gf.primitiveFieldRef(), dvs.value(), gf1.primitiveField()); \ Foam::opFunc(gf.boundaryFieldRef(), dvs.value(), gf1.boundaryField()); \ gf.oriented() = gf1.oriented(); \ } \ \ template \ class PatchField, class GeoMesh> \ tmp::type, PatchField, GeoMesh>> \ operator op \ ( \ const dimensioned& dvs, \ const GeometricField& gf1 \ ) \ { \ typedef typename product::type productType; \ \ auto tres = \ tmp>::New \ ( \ IOobject \ ( \ '(' + dvs.name() + #op + gf1.name() + ')', \ gf1.instance(), \ gf1.db(), \ IOobject::NO_READ, \ IOobject::NO_WRITE \ ), \ gf1.mesh(), \ dvs.dimensions() op gf1.dimensions() \ ); \ \ Foam::opFunc(tres.ref(), dvs, gf1); \ \ return tres; \ } \ \ template \ < \ class Form, \ class Cmpt, \ direction nCmpt, \ class Type, template class PatchField, \ class GeoMesh \ > \ tmp::type, PatchField, GeoMesh>> \ operator op \ ( \ const VectorSpace& vs, \ const GeometricField& gf1 \ ) \ { \ return dimensioned(static_cast(vs)) op gf1; \ } \ \ template \ class PatchField, class GeoMesh> \ tmp::type, PatchField, GeoMesh>> \ operator op \ ( \ const dimensioned& dvs, \ const tmp>& tgf1 \ ) \ { \ typedef typename product::type productType; \ \ const GeometricField& gf1 = tgf1(); \ \ auto tres = \ reuseTmpGeometricField::New \ ( \ tgf1, \ '(' + dvs.name() + #op + gf1.name() + ')', \ dvs.dimensions() op gf1.dimensions() \ ); \ \ Foam::opFunc(tres.ref(), dvs, gf1); \ \ tgf1.clear(); \ \ return tres; \ } \ \ template \ < \ class Form, \ class Cmpt, \ direction nCmpt, \ class Type, template class PatchField, \ class GeoMesh \ > \ tmp::type, PatchField, GeoMesh>> \ operator op \ ( \ const VectorSpace& vs, \ const tmp>& tgf1 \ ) \ { \ return dimensioned(static_cast(vs)) op tgf1; \ } PRODUCT_OPERATOR(typeOfSum, +, add) PRODUCT_OPERATOR(typeOfSum, -, subtract) PRODUCT_OPERATOR(outerProduct, *, outer) PRODUCT_OPERATOR(crossProduct, ^, cross) PRODUCT_OPERATOR(innerProduct, &, dot) PRODUCT_OPERATOR(scalarProduct, &&, dotdot) #undef PRODUCT_OPERATOR // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #include "undefFieldFunctionsM.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //