diff --git a/applications/test/expressionTemplates/Make/files b/applications/test/expressionTemplates/Make/files
new file mode 100644
index 0000000000..9d866b294b
--- /dev/null
+++ b/applications/test/expressionTemplates/Make/files
@@ -0,0 +1,5 @@
+Test-expressionTemplates-volFields.C
+/* Test-expressionTemplates-pointFields.C */
+/* Test-expressionTemplates-Fields.C */
+
+EXE = $(FOAM_USER_APPBIN)/Test-expressionTemplates
diff --git a/applications/test/expressionTemplates/Make/options b/applications/test/expressionTemplates/Make/options
new file mode 100644
index 0000000000..ede08caa60
--- /dev/null
+++ b/applications/test/expressionTemplates/Make/options
@@ -0,0 +1,11 @@
+EXE_INC = \
+ -O0 \
+ -I$(FOAM_SRC)/meshTools/lnInclude \
+ -I$(FOAM_SRC)/finiteVolume/lnInclude \
+
+EXE_LIBS = \
+/* -rpath /Volumes/case_sensitive/OpenFOAM/work/feature-et/platforms */ \
+/* -rpath /Volumes/case_sensitive/OpenFOAM/work/feature-et/platforms/darwin64GccDPInt32Opt/lib */ \
+/* -rpath /Volumes/case_sensitive/OpenFOAM/work/feature-et/platforms/darwin64GccDPInt32Opt/lib/$(FOAM_MPI) */\
+ -L/Volumes/case_sensitive/OpenFOAM/work/feature-et/platforms/darwin64GccDPInt32Opt/lib \
+ -lfiniteVolume
diff --git a/applications/test/expressionTemplates/Test-expressionTemplates-pointFields.C b/applications/test/expressionTemplates/Test-expressionTemplates-pointFields.C
new file mode 100644
index 0000000000..47b0017c11
--- /dev/null
+++ b/applications/test/expressionTemplates/Test-expressionTemplates-pointFields.C
@@ -0,0 +1,126 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | www.openfoam.com
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2025 M. Janssens
+-------------------------------------------------------------------------------
+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 .
+
+Application
+ Test-expressionTemplates
+
+\*---------------------------------------------------------------------------*/
+
+#include "Time.H"
+#include "argList.H"
+#include "polyMesh.H"
+#include "pointMesh.H"
+#include "pointFields.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+int main(int argc, char *argv[])
+{
+ #include "setRootCase.H"
+
+ #include "createTime.H"
+ #include "createPolyMesh.H"
+
+ {
+ scalarField vals0({1.0, 2.0, 3.0});
+ const Expression::ListConstRefWrap wvals0(vals0);
+
+ scalarField vals1;
+ Expression::ListRefWrap wvals1(vals1.size(), vals1);
+ wvals1 = wvals0;
+ return 0;
+ }
+
+
+
+
+ const pointMesh& pMesh = pointMesh::New(mesh);
+
+ // Field, dimensionedScalar as List expression
+ {
+ scalarField vals({1.0, 2.0, 3.0});
+ dimensionedScalar d(dimless, 4.0);
+
+ scalarField result(d.expr(vals.size())*vals.expr());
+
+ Pout<< "result:" << result << endl;
+ }
+
+ Info<< "Reading field p\n" << endl;
+ pointScalarField p
+ (
+ IOobject
+ (
+ "pointDisplacement",
+ runTime.timeName(),
+ pMesh.thisDb(),
+ IOobject::MUST_READ,
+ IOobject::AUTO_WRITE
+ ),
+ pMesh
+ );
+
+ pointScalarField result
+ (
+ IOobject
+ (
+ "result",
+ runTime.timeName(),
+ pMesh.thisDb(),
+ IOobject::NO_READ,
+ IOobject::NO_WRITE,
+ IOobject::NO_REGISTER
+ ),
+ pMesh,
+ dimensionedScalar("zero", Foam::sqr(p().dimensions()), 0)
+ );
+
+ // Construct value + dimensions with correct sizing
+ const auto oneField(dimensionedScalar(dimless, 1.0).expr(p));
+
+ // Make expression
+ auto expression = oneField * p.expr() + p.expr();
+
+ // Combine expressions
+ auto newExpression = sqr(expression);
+
+ // Assign values
+ result = newExpression;
+
+ DebugVar(result);
+
+
+ // Construct from expression
+ pointScalarField result2("result2", pMesh, sqrt(p.expr()));
+
+ DebugVar(result2);
+
+ return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/applications/test/expressionTemplates/Test-expressionTemplates-volFields.C b/applications/test/expressionTemplates/Test-expressionTemplates-volFields.C
new file mode 100644
index 0000000000..bd5b2a3219
--- /dev/null
+++ b/applications/test/expressionTemplates/Test-expressionTemplates-volFields.C
@@ -0,0 +1,451 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | www.openfoam.com
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+ Copyright (C) 2011-2016 OpenFOAM Foundation
+-------------------------------------------------------------------------------
+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 .
+
+Application
+ volPointInterpolationTest
+
+\*---------------------------------------------------------------------------*/
+
+#include "Time.H"
+#include "argList.H"
+#include "fvMesh.H"
+#include "ListExpression.H"
+#include "GeometricFieldExpression.H"
+#include "fvCFD.H"
+#include "fvMatrixExpression.H"
+#include
+#include
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+tmp someFunction(const volScalarField& fld)
+{
+ return fld*1.0001;
+}
+
+
+template
+void fusedGaussFvmLaplacian
+(
+ fvMatrix& fvm,
+ const surfaceInterpolationScheme& interpGammaScheme,
+ const fv::snGradScheme& snGradScheme,
+ const GeometricField& gamma,
+ const GeometricField& vf
+)
+{
+ // Replacement for gaussLaplacianScheme::fvmLaplacian with scalar gamma
+ typedef GeometricField surfaceType;
+
+ const auto& mesh = vf.mesh();
+
+ // Expression for weights
+ const auto weights = interpGammaScheme.weights(gamma).expr();
+
+ // Expression for gamma_face * magSf
+ const auto gammaMagSf =
+ Expression::interpolate(gamma.expr(), weights, mesh)
+ * mesh.magSf().expr();
+
+ // Expression for deltaCoeffs
+ const auto deltaCoeffs = snGradScheme.deltaCoeffs(vf).expr();
+
+ // Construct matrix
+ Expression::fvmLaplacianUncorrected(fvm, gammaMagSf, deltaCoeffs);
+
+ if (snGradScheme.corrected())
+ {
+ // Wrap correction
+ const auto corr(snGradScheme.correction(vf).expr());
+ const auto V = mesh.V().expr();
+
+ if (mesh.fluxRequired(vf.name()))
+ {
+ fvm.faceFluxCorrectionPtr() = std::make_unique
+ (
+ IOobject
+ (
+ "faceFluxCorr",
+ mesh.time().timeName(),
+ mesh,
+ IOobject::NO_READ,
+ IOobject::NO_WRITE,
+ IOobject::NO_REGISTER
+ ),
+ mesh,
+ gamma.dimensions()
+ *mesh.magSf().dimensions()
+ *corr.data().dimensions()
+ );
+ auto& faceFluxCorr = *fvm.faceFluxCorrectionPtr();
+ faceFluxCorr = gammaMagSf*corr;
+
+ fvm.source() =
+ fvm.source().expr()
+ - (
+ V * fvc::div
+ (
+ faceFluxCorr
+ )().primitiveField().expr()
+ );
+ }
+ else
+ {
+ // Temporary field
+ surfaceType faceFluxCorr
+ (
+ IOobject
+ (
+ "faceFluxCorr",
+ mesh.time().timeName(),
+ mesh,
+ IOobject::NO_READ,
+ IOobject::NO_WRITE,
+ IOobject::NO_REGISTER
+ ),
+ mesh,
+ gamma.dimensions()
+ *mesh.magSf().dimensions()
+ *corr.data().dimensions()
+ );
+ faceFluxCorr = gammaMagSf*corr;
+
+ fvm.source() =
+ fvm.source().expr()
+ - (
+ V * fvc::div
+ (
+ faceFluxCorr
+ )().primitiveField().expr()
+ );
+ }
+ }
+}
+
+
+using namespace std::chrono;
+
+int main(int argc, char *argv[])
+{
+ #include "setRootCase.H"
+ #include "createTime.H"
+ #include "createMesh.H"
+
+ Info<< "Reading field p\n" << endl;
+ volScalarField p
+ (
+ IOobject
+ (
+ "p",
+ runTime.timeName(),
+ mesh.thisDb(),
+ IOobject::MUST_READ,
+ IOobject::AUTO_WRITE
+ ),
+ mesh
+ );
+
+ {
+ volScalarField p2("p2", p);
+ DebugVar(p2.boundaryFieldRef());
+
+ for (auto& pf : p.boundaryFieldRef())
+ {
+ scalarField newVals(pf.size());
+ forAll(pf, i)
+ {
+ newVals[i] = scalar(i);
+ }
+ pf == newVals;
+ }
+
+ //std::vector ptrs;
+ // List ptrs;
+ // for (const auto& pp : p.boundaryField())
+ // {
+ // ptrs.push_back(&pp);
+ // }
+ DebugVar(sizeof(long));
+ DebugVar(p.boundaryField());
+ Expression::ListsConstRefWrap expr(p.boundaryField());
+
+ const auto twoA = expr + expr;
+ Expression::ListsRefWrap expr2(p2.boundaryFieldRef());
+ Pout<< "**before assignment twoA:" << twoA.size()
+ << " expr2:" << expr2.size() << endl;
+ expr2 = twoA;
+ Pout<< "**after assignment twoA:" << twoA.size()
+ << " expr2:" << expr2.size() << endl;
+ DebugVar(p2.boundaryField());
+ // forAll(expr, i)
+ // {
+ // Pout<< "i:" << i
+ // //<< " expr:" << expr[i]
+ // //<< " twoA:" << twoA[i]
+ // << " expr2:" << expr2[i]
+ // << endl;
+ // }
+ return 0;
+ }
+
+ {
+ //DebugVar(linearInterpolate(p));
+ //auto tweights = linear(mesh).weights(p);
+ //DebugVar(tweights);
+
+ surfaceScalarField result
+ (
+ IOobject
+ (
+ "result",
+ runTime.timeName(),
+ mesh.thisDb(),
+ IOobject::NO_READ,
+ IOobject::NO_WRITE,
+ IOobject::NO_REGISTER
+ ),
+ mesh,
+ dimensionedScalar(p.dimensions(), 0)
+ );
+ //result = Expression::interpolate
+ //(
+ // p.expr(),
+ // tweights().expr(),
+ // mesh
+ //);
+
+ result = Expression::linearInterpolate(p.expr(), mesh);
+
+
+ DebugVar(result);
+
+ return 0;
+ }
+
+
+
+ volScalarField p2
+ (
+ IOobject
+ (
+ "p",
+ runTime.timeName(),
+ mesh.thisDb(),
+ IOobject::MUST_READ,
+ IOobject::AUTO_WRITE,
+ IOobject::NO_REGISTER
+ ),
+ mesh
+ );
+
+ // Expresions of volFields
+ {
+ volScalarField result
+ (
+ IOobject
+ (
+ "result",
+ runTime.timeName(),
+ mesh.thisDb(),
+ IOobject::NO_READ,
+ IOobject::NO_WRITE,
+ IOobject::NO_REGISTER
+ ),
+ mesh,
+ dimensionedScalar(p.dimensions(), 0)
+ );
+
+ {
+ Pout<< "No expression templates:" << endl;
+ const high_resolution_clock::time_point t1 =
+ high_resolution_clock::now();
+ result = p + p2;
+ const high_resolution_clock::time_point t2 =
+ high_resolution_clock::now();
+ const duration time_span = t2 - t1;
+ Pout<< "Operation time:" << time_span.count() << endl;
+ }
+ {
+ Pout<< "With expression templates:" << endl;
+ const high_resolution_clock::time_point t1 =
+ high_resolution_clock::now();
+ result = p.expr() + p2.expr();
+ const high_resolution_clock::time_point t2 =
+ high_resolution_clock::now();
+ const duration time_span = t2 - t1;
+ Pout<< "Operation time:" << time_span.count() << endl;
+ }
+
+// const auto oldDimensions = p.dimensions();
+// p.dimensions().reset(dimless);
+// p2.dimensions().reset(dimless);
+// result.dimensions().reset(dimless);
+// {
+//
+// Pout<< "Complex expression : No expression templates:" << endl;
+// const high_resolution_clock::time_point t1 =
+// high_resolution_clock::now();
+// result = cos(p + 0.5*sqrt(p2-sin(p)));
+// const high_resolution_clock::time_point t2 =
+// high_resolution_clock::now();
+// const duration time_span = t2 - t1;
+// Pout<< "Operation time:" << time_span.count() << endl;
+// }
+// {
+// Pout<< "Complex expression : With expression templates:" << endl;
+// const high_resolution_clock::time_point t1 =
+// high_resolution_clock::now();
+// const auto zeroDotFive
+// (
+// dimensionedScalar(dimless, 0.5).expr(p)
+// );
+// result = cos(p.expr() + zeroDotFive*sqrt(p2.expr()-sin(p.expr())));
+// const high_resolution_clock::time_point t2 =
+// high_resolution_clock::now();
+// const duration time_span = t2 - t1;
+// Pout<< "Operation time:" << time_span.count() << endl;
+// }
+// p.dimensions().reset(oldDimensions);
+// p2.dimensions().reset(oldDimensions);
+// result.dimensions().reset(oldDimensions);
+
+ return 0;
+// auto expression = someFunction(p).expr() + someFunction(p).expr();
+// result = expression;
+// DebugVar(result);
+ }
+ {
+ volScalarField result
+ (
+ IOobject
+ (
+ "result",
+ runTime.timeName(),
+ mesh.thisDb(),
+ IOobject::NO_READ,
+ IOobject::NO_WRITE,
+ IOobject::NO_REGISTER
+ ),
+ mesh,
+ dimensionedScalar(p.dimensions(), 0)
+ );
+ auto expression = someFunction(p).expr() + someFunction(p).expr();
+ result = expression;
+ DebugVar(result);
+ }
+
+ // Expresions of volFields
+ {
+ volScalarField result
+ (
+ "result",
+ mesh,
+ sqr(p.expr() + p.expr())
+ );
+ DebugVar(result);
+ }
+ {
+ // Fill p with some values
+ forAll(p, celli)
+ {
+ p[celli] = celli;
+ }
+ p.correctBoundaryConditions();
+
+ // Interpolate to surface field
+ surfaceScalarField result
+ (
+ "result",
+ mesh,
+ Expression::interpolate //
+ (
+ p.expr(),
+ mesh.surfaceInterpolation::weights().expr(),
+ mesh
+ )
+ );
+ DebugVar(result);
+ }
+ {
+ // For testing as a replacement of laplacian weights
+ const volScalarField gamma
+ (
+ IOobject
+ (
+ "gamma",
+ runTime.timeName(),
+ mesh,
+ IOobject::NO_READ,
+ IOobject::NO_WRITE,
+ IOobject::NO_REGISTER
+ ),
+ mesh,
+ dimensionedScalar(dimless, 1.0)
+ );
+
+ fvMatrix fvm
+ (
+ p,
+ gamma.dimensions()*mesh.magSf().dimensions()*p.dimensions()
+ );
+
+ const linear interpGammaScheme(mesh);
+ const fv::correctedSnGrad snGradScheme(mesh);
+
+ fusedGaussFvmLaplacian
+ (
+ fvm,
+ interpGammaScheme,
+ snGradScheme,
+ gamma,
+ p
+ );
+
+ DebugVar(fvm.source());
+ }
+
+
+
+ // Expressions of fvMatrix
+ {
+ tmp> tm0(fvm::laplacian(p));
+ const fvMatrix& m0 = tm0();
+ DebugVar(m0.dimensions());
+
+ tmp> tm1(fvm::laplacian(p));
+ const fvMatrix& m1 = tm1();
+ DebugVar(m1.dimensions());
+
+ fvMatrix m2(p, m0.expr() + m1.expr());
+ DebugVar(m2.dimensions());
+ }
+
+ return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/etc/config.sh/settings b/etc/config.sh/settings
index a615345631..ae5e714e64 100644
--- a/etc/config.sh/settings
+++ b/etc/config.sh/settings
@@ -81,8 +81,8 @@ Darwin)
case "$WM_COMPILE_CONTROL" in
(*version=*) ;;
(*)
- WM_COMPILER=Clang
- echo "openfoam (darwin): using clang instead of gcc" 1>&2
+ #WM_COMPILER=Clang
+ #echo "openfoam (darwin): using clang instead of gcc" 1>&2
;;
esac
fi
diff --git a/src/Allwmake b/src/Allwmake
index 04f82ffe97..8e87d20311 100755
--- a/src/Allwmake
+++ b/src/Allwmake
@@ -55,8 +55,6 @@ wmake $targetType fileFormats
wmake $targetType surfMesh
wmake $targetType meshTools
-#------------------------------------------------------------------------------
-
wmake $targetType finiteArea
wmake $targetType finiteVolume
wmake $targetType fused/finiteVolume
diff --git a/src/OpenFOAM/containers/Lists/List/List.H b/src/OpenFOAM/containers/Lists/List/List.H
index eaaaaea6a9..fd2b176638 100644
--- a/src/OpenFOAM/containers/Lists/List/List.H
+++ b/src/OpenFOAM/containers/Lists/List/List.H
@@ -45,6 +45,7 @@ SourceFiles
#include "autoPtr.H"
#include "UList.H"
+#include "SLListFwd.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -65,7 +66,6 @@ typedef List boolList; //!< A List of bools
typedef List charList; //!< A List of chars
typedef List