diff --git a/bin/XiEngineFoam b/bin/XiEngineFoam
deleted file mode 100755
index acad90ca77..0000000000
--- a/bin/XiEngineFoam
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# ========= |
-# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
-# \\ / O peration | Website: https://openfoam.org
-# \\ / A nd | Copyright (C) 2021 OpenFOAM Foundation
-# \\/ M anipulation |
-#------------------------------------------------------------------------------
-# 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 .
-#
-# Script
-# XiEngineFoam
-#
-# Description
-# Script to inform the user that XiEngineFoam has been replaced by the more
-# general XiFoam solver.
-#
-#------------------------------------------------------------------------------
-
-cat << EOF
-
-The XiEngineFoam solver has solver has been replaced by the more general XiFoam
-solver, which supports engine mesh motion using an appropriate
-fvMeshMover. e.g. layeredEngine
-
-To run a XiEngineFoam case in XiFoam add a mover entry in
-constant/dynamicMeshDict
-e.g. from the tutorials/combustion/XiFoam/RAS/kivaTest case:
-
-mover
-{
- type layeredEngine;
-
- libs ("libfvMeshMovers.so");
-
- conRodLength 0.147;
- bore 0.092;
- stroke 0.08423;
- clearance 0.00115;
- pistonLayers 0;
-}
-
-EOF
-
-#------------------------------------------------------------------------------
diff --git a/bin/coldEngineFoam b/bin/coldEngineFoam
deleted file mode 100755
index 76775793e7..0000000000
--- a/bin/coldEngineFoam
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/sh
-#------------------------------------------------------------------------------
-# ========= |
-# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
-# \\ / O peration | Website: https://openfoam.org
-# \\ / A nd | Copyright (C) 2021-2023 OpenFOAM Foundation
-# \\/ M anipulation |
-#------------------------------------------------------------------------------
-# 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 .
-#
-# Script
-# coldEngineFoam
-#
-# Description
-# Script to inform the user that coldEngineFoam has been replaced by the
-# more general fluid solver module.
-#
-#------------------------------------------------------------------------------
-
-cat << EOF
-
-The coldEngineFoam solver has solver has been replaced by the more general
-fluid solver module, which supports engine mesh motion using an appropriate
-fvMeshMover. e.g. layeredEngine
-
-To run a coldEngineFoam case with
-
- foamRun -solver fluid
-
-add a mover entry in constant/dynamicMeshDict
-e.g. from the tutorials/fluid/RAS/kivaTest case:
-
-mover
-{
- type layeredEngine;
-
- libs ("libfvMeshMovers.so");
-
- conRodLength 0.147;
- bore 0.092;
- stroke 0.08423;
- clearance 0.00115;
- pistonLayers 0;
-}
-
-EOF
-
-#------------------------------------------------------------------------------
diff --git a/src/fvMeshMovers/multiValveEngine/Make/files b/src/fvMeshMovers/multiValveEngine/Make/files
new file mode 100644
index 0000000000..c2ee3246b5
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/Make/files
@@ -0,0 +1,9 @@
+multiValveEngine.C
+movingObject.C
+piston.C
+valve.C
+valveList.C
+crankConnectingRodMotion/crankConnectingRodMotion.C
+pistonPointEdgeData/pistonPointEdgeData.C
+
+LIB = $(FOAM_LIBBIN)/libfvMeshMoversMultiValveEngine
diff --git a/src/fvMeshMovers/multiValveEngine/Make/options b/src/fvMeshMovers/multiValveEngine/Make/options
new file mode 100644
index 0000000000..ea345a9f24
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/Make/options
@@ -0,0 +1,7 @@
+EXE_INC = \
+ -I$(LIB_SRC)/finiteVolume/lnInclude \
+ -I$(LIB_SRC)/meshTools/lnInclude \
+
+LIB_LIBS = \
+ -lfiniteVolume \
+ -lmeshTools
diff --git a/src/fvMeshMovers/multiValveEngine/crankConnectingRodMotion/crankConnectingRodMotion.C b/src/fvMeshMovers/multiValveEngine/crankConnectingRodMotion/crankConnectingRodMotion.C
new file mode 100644
index 0000000000..c2bbec6eb0
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/crankConnectingRodMotion/crankConnectingRodMotion.C
@@ -0,0 +1,77 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+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 "crankConnectingRodMotion.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace Function1s
+{
+ addScalarFunction1(crankConnectingRodMotion);
+}
+}
+
+
+// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
+
+void Foam::Function1s::crankConnectingRodMotion::read(const dictionary& dict)
+{
+ conRodLength_ = dict.lookup("conRodLength");
+ stroke_ = dict.lookup("stroke");
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::Function1s::crankConnectingRodMotion::crankConnectingRodMotion
+(
+ const word& name,
+ const dictionary& dict
+)
+:
+ Function1(name)
+{
+ read(dict);
+}
+
+
+// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
+
+Foam::Function1s::crankConnectingRodMotion::~crankConnectingRodMotion()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+void Foam::Function1s::crankConnectingRodMotion::write(Ostream& os) const
+{
+ writeEntry(os, "conRodLength", conRodLength_);
+ writeEntry(os, "stroke", stroke_);
+}
+
+
+// ************************************************************************* //
diff --git a/src/fvMeshMovers/multiValveEngine/crankConnectingRodMotion/crankConnectingRodMotion.H b/src/fvMeshMovers/multiValveEngine/crankConnectingRodMotion/crankConnectingRodMotion.H
new file mode 100644
index 0000000000..a72acc1306
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/crankConnectingRodMotion/crankConnectingRodMotion.H
@@ -0,0 +1,166 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+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 .
+
+Class
+ Foam::Function1s::crankConnectingRodMotion
+
+Description
+ Crank and connecting-rod motion function for piston engines etc.
+
+ \c value returns the current piston position as a function of
+ the crank-angle in degrees.
+
+ Usage:
+ \verbatim
+
+ {
+ type crankConnectingRodMotion;
+
+ conRodLength 0.2;
+ stroke 0.12;
+ }
+ \endverbatim
+
+See also
+ Foam::Function1
+
+SourceFiles
+ crankConnectingRodMotionI.H
+ crankConnectingRodMotion.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef crankConnectingRodMotion_H
+#define crankConnectingRodMotion_H
+
+#include "Function1.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace Function1s
+{
+
+/*---------------------------------------------------------------------------*\
+ Class crankConnectingRodMotion Declaration
+\*---------------------------------------------------------------------------*/
+
+class crankConnectingRodMotion
+:
+ public Function1
+{
+ // Private data
+
+ //- Connecting-rod length
+ scalar conRodLength_;
+
+ //- Stroke
+ scalar stroke_;
+
+
+ // Private Member Functions
+
+ //- Read the coefficients from the given dictionary
+ void read(const dictionary& dict);
+
+
+public:
+
+ // Runtime type information
+ TypeName("crankConnectingRodMotion");
+
+
+ // Constructors
+
+ //- Construct from name and dictionary
+ crankConnectingRodMotion
+ (
+ const word& name,
+ const dictionary& dict
+ );
+
+ //- Construct and return a clone
+ virtual tmp> clone() const
+ {
+ return tmp>
+ (
+ new crankConnectingRodMotion(*this)
+ );
+ }
+
+
+ //- Destructor
+ virtual ~crankConnectingRodMotion();
+
+
+ // Member Functions
+
+ //- Return position for crank-angle theta in deg
+ virtual inline scalar value(const scalar theta) const;
+
+ //- Not implemented
+ virtual inline tmp> value(const scalarField&) const;
+
+ //- Not implemented
+ virtual inline scalar integral
+ (
+ const scalar,
+ const scalar
+ ) const;
+
+ //- Not implemented
+ virtual inline tmp> integral
+ (
+ const scalarField&,
+ const scalarField&
+ ) const;
+
+
+ //- Write data to dictionary stream
+ virtual void write(Ostream& os) const;
+
+
+ // Member Operators
+
+ //- Disallow default bitwise assignment
+ void operator=(const crankConnectingRodMotion&) = delete;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Function1s
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#ifdef NoRepository
+ #include "crankConnectingRodMotionI.H"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fvMeshMovers/multiValveEngine/crankConnectingRodMotion/crankConnectingRodMotionI.H b/src/fvMeshMovers/multiValveEngine/crankConnectingRodMotion/crankConnectingRodMotionI.H
new file mode 100644
index 0000000000..aef15f073f
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/crankConnectingRodMotion/crankConnectingRodMotionI.H
@@ -0,0 +1,81 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+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 "crankConnectingRodMotion.H"
+#include "unitConversion.H"
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+inline Foam::scalar Foam::Function1s::crankConnectingRodMotion::value
+(
+ const scalar theta
+) const
+{
+ return
+ (
+ conRodLength_ + stroke_/2
+ )
+ - (
+ stroke_*cos(degToRad(theta))/2
+ + sqrt(sqr(conRodLength_) - sqr(stroke_*sin(degToRad(theta))/2))
+ );
+}
+
+
+inline Foam::tmp>
+Foam::Function1s::crankConnectingRodMotion::value
+(
+ const scalarField&
+) const
+{
+ NotImplemented;
+ return tmp>(nullptr);
+}
+
+
+inline Foam::scalar Foam::Function1s::crankConnectingRodMotion::integral
+(
+ const scalar,
+ const scalar
+) const
+{
+ NotImplemented;
+ return NaN;
+}
+
+
+inline Foam::tmp>
+Foam::Function1s::crankConnectingRodMotion::integral
+(
+ const scalarField&,
+ const scalarField&
+) const
+{
+ NotImplemented;
+ return tmp>(nullptr);
+}
+
+
+// ************************************************************************* //
diff --git a/src/fvMeshMovers/multiValveEngine/movingObject.C b/src/fvMeshMovers/multiValveEngine/movingObject.C
new file mode 100644
index 0000000000..8da4dc20df
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/movingObject.C
@@ -0,0 +1,328 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+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 "multiValveEngine.H"
+#include "pointConstraints.H"
+#include "polyCellSet.H"
+#include "syncTools.H"
+
+// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
+
+void Foam::fvMeshMovers::multiValveEngine::movingObject::calcScale
+(
+ const pointMesh& pMesh,
+ const scalarField& pDistMoving,
+ const scalarField& pDistStatic,
+ scalar dMoving,
+ scalar dMax,
+ scalar dStatic
+)
+{
+ scalarField& scale = scale_.primitiveFieldRef();
+
+ forAll(scale, pi)
+ {
+ // If original dMoving and dStatic regions overlay set to zero.
+ // This may happen when e.g. valve-piston distance becomes small.
+ if
+ (
+ ((pDistMoving[pi] - dMoving) <= 0) &&
+ ((pDistStatic[pi] - dStatic) <= 0)
+ )
+ {
+ dMoving = 0;
+ dStatic = 0;
+ }
+
+ // - Near static patches
+ if (pDistStatic[pi] - dStatic <= 0)
+ {
+ scale[pi] = 0;
+ }
+ // - Near object
+ else if (pDistMoving[pi] - dMoving <= 0)
+ {
+ scale[pi] = 1;
+ }
+ // - Outside outer boundary
+ else if (dMax - pDistMoving[pi] <= 0)
+ {
+ scale[pi] = 0;
+ }
+ // Linear scaling from the moving patch:
+ // patch->dMoving: 1
+ // dMoving->min(dMax, min(dStatic - dh, dFrozenZone)): linear 1->0
+ else
+ {
+ const scalar d1 = pDistMoving[pi] - dMoving;
+ const scalar d2 = min
+ (
+ dMax - pDistMoving[pi],
+ pDistStatic[pi] - dStatic
+ );
+ scale[pi] = 1 - d1/(d1 + d2 + rootVSmall);
+ }
+ }
+
+ // Convert the scale function to a cosine
+ if (cosine_)
+ {
+ scale =
+ min
+ (
+ max
+ (
+ 0.5
+ - 0.5
+ *cos(scale_.primitiveField()*constant::mathematical::pi),
+ scalar(0)
+ ),
+ scalar(1)
+ );
+ }
+
+ pointConstraints::New(pMesh).constrain(scale_);
+
+ if (debug)
+ {
+ scale_.write();
+ }
+}
+
+
+void Foam::fvMeshMovers::multiValveEngine::movingObject::transformPoints
+(
+ pointField& newPoints,
+ const vector& translationVector
+)
+{
+ // Explicit filtering of displacement to avoid pointMesh looping
+ if (mag(translationVector) < small)
+ {
+ executionCount_++;
+ return;
+ }
+
+ forAll(newPoints, pi)
+ {
+ const point displacementVector = scale_[pi]*translationVector;
+ if (mag(displacementVector) > small)
+ {
+ newPoints[pi] += displacementVector;
+ }
+ }
+
+ executionCount_++;
+}
+
+
+void Foam::fvMeshMovers::multiValveEngine::movingObject::createStaticPatchSet()
+{
+ staticPatchSet_.clear();
+
+ forAll(meshMover_.mesh().boundaryMesh(), patchI)
+ {
+ const polyPatch& pp = meshMover_.mesh().boundaryMesh()[patchI];
+
+ // Exclude non-static patches
+ if
+ (
+ !polyPatch::constraintType(pp.type())
+ && !meshMover_.slidingPatchSet_.found(pp.index())
+ && !patchSet.found(pp.index())
+ )
+ {
+ staticPatchSet_.insert(pp.index());
+ }
+ }
+}
+
+
+void Foam::fvMeshMovers::multiValveEngine::movingObject::initPatchSets()
+{
+ // Set patch-sets
+ patchSet_ = meshMover_.mesh().boundaryMesh().patchSet
+ (
+ wordReList(dict_.lookup("patches"))
+ );
+
+ if (patchSet_.empty())
+ {
+ FatalErrorInFunction
+ << "Empty patchSet in " << dict_.name()
+ << exit(FatalError);
+ }
+
+ createStaticPatchSet();
+}
+
+
+Foam::labelHashSet
+Foam::fvMeshMovers::multiValveEngine::movingObject::movingPointZones() const
+{
+ labelHashSet movingPointZones;
+
+ if (movingPointZones_.size())
+ {
+ forAll(movingPointZones_, i)
+ {
+ const labelList indices
+ (
+ meshMover_.mesh().pointZones().findIndices(movingPointZones_[i])
+ );
+
+ if (indices.size())
+ {
+ movingPointZones.insert(indices);
+ Info<< " pointZone " << movingPointZones_[i]
+ << " will move with the object " << name << endl;
+ }
+ else
+ {
+ Info<< " movingZone " << movingPointZones_[i]
+ << " not found in pointZones" << endl;
+ }
+ }
+ }
+
+ return movingPointZones;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::fvMeshMovers::multiValveEngine::movingObject::movingObject
+(
+ const word& objectName,
+ const multiValveEngine& engine,
+ const dictionary& dict
+)
+:
+ dict_(dict),
+ meshMover_(engine),
+ name(objectName),
+ axis(dict.lookup("axis")),
+ motion_(Function1::New("motion", dict)),
+ maxMotionDistance_
+ (
+ dict.lookupOrDefault("maxMotionDistance", great)
+ ),
+ movingFrozenLayerThickness_
+ (
+ dict.lookupOrDefault("movingFrozenLayerThickness", 0)
+ ),
+ staticFrozenLayerThickness_
+ (
+ dict.lookupOrDefault("staticFrozenLayerThickness", 0)
+ ),
+ movingPointZones_
+ (
+ dict.lookupOrDefault("movingZones", wordReList::null())
+ ),
+ scale_
+ (
+ IOobject
+ (
+ "motionScale_" + name,
+ meshMover_.mesh().time().timeName(),
+ meshMover_.mesh(),
+ IOobject::NO_READ,
+ IOobject::NO_WRITE
+ ),
+ pointMesh::New(meshMover_.mesh()),
+ dimensionedScalar(dimless, 0)
+ ),
+ cosine_(dict.lookupOrDefault("cosineScaling", false)),
+ fractionalTravelInterval_
+ (
+ dict.lookupOrDefault("fractionalTravelInterval", 1)
+ ),
+ executionCount_(0),
+ position0_(-great),
+ patchSet(patchSet_)
+{
+ Info << indent << "Setting motion for " << name << endl;
+
+ scalar maxTravel = -great;
+ scalar minTravel = great;
+
+ const scalar userBeginTime
+ (
+ meshMover_.mesh().time().timeToUserTime
+ (
+ meshMover_.mesh().time().beginTime().value()
+ )
+ );
+
+ const scalar userEndTime
+ (
+ meshMover_.mesh().time().timeToUserTime
+ (
+ meshMover_.mesh().time().endTime().value()
+ )
+ );
+
+ const scalar userDeltaT = meshMover_.userDeltaT();
+
+ scalar userTime = userBeginTime;
+
+ while (userTime <= userEndTime)
+ {
+ const scalar position = motion_->value(userTime);
+
+ maxTravel = max(maxTravel, position);
+ minTravel = min(minTravel, position);
+
+ userTime += userDeltaT;
+ }
+
+ travel_ = maxTravel - minTravel;
+
+ initPatchSets();
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+void Foam::fvMeshMovers::multiValveEngine::movingObject::mapMesh
+(
+ const polyMeshMap&
+)
+{
+ // Reset patch sets.
+ initPatchSets();
+
+ // scale_ is resized by the meshToMesh mapper
+ scale_ = Zero;
+
+ // Reset count of the scale_ field updates
+ executionCount_ = 0;
+
+ // Reset position at last scale update
+ position0_ = -great;
+}
+
+
+// ************************************************************************* //
diff --git a/src/fvMeshMovers/multiValveEngine/multiValveEngine.C b/src/fvMeshMovers/multiValveEngine/multiValveEngine.C
new file mode 100644
index 0000000000..ebc7a93b00
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/multiValveEngine.C
@@ -0,0 +1,237 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+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 "multiValveEngine.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace fvMeshMovers
+{
+ defineTypeNameAndDebug(multiValveEngine, 0);
+ addToRunTimeSelectionTable(fvMeshMover, multiValveEngine, fvMesh);
+}
+}
+
+Foam::word Foam::fvMeshMovers::multiValveEngine::cylinderHeadName
+(
+ "cylinderHead"
+);
+
+
+// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
+
+Foam::labelHashSet
+Foam::fvMeshMovers::multiValveEngine::findLinerPatchSet() const
+{
+ return mesh().boundaryMesh().patchSet
+ (
+ wordReList(dict().lookup("linerPatches"))
+ );
+}
+
+
+Foam::labelHashSet Foam::fvMeshMovers::multiValveEngine::findSlidingPatchSet()
+{
+ return mesh().boundaryMesh().patchSet
+ (
+ wordReList(dict().lookup("slidingPatches"))
+ );
+}
+
+
+Foam::labelHashSet Foam::fvMeshMovers::multiValveEngine::findStaticPatchSet()
+{
+ labelHashSet movingPatchSet(piston_.patchSet_);
+
+ forAll(valves_, valvei)
+ {
+ movingPatchSet += valves_[valvei].patchSet_;
+ }
+
+ labelHashSet staticPatchSet;
+
+ forAll(mesh().boundaryMesh(), patchi)
+ {
+ const polyPatch& pp = mesh().boundaryMesh()[patchi];
+
+ // Exclude non-static patches
+ if
+ (
+ !polyPatch::constraintType(pp.type())
+ && !slidingPatchSet_.found(pp.index())
+ && !movingPatchSet.found(pp.index())
+ )
+ {
+ staticPatchSet.insert(pp.index());
+ }
+ }
+
+ return staticPatchSet;
+}
+
+
+Foam::labelHashSet
+Foam::fvMeshMovers::multiValveEngine::staticPointZones() const
+{
+ labelHashSet staticPointZones;
+
+ if (frozenPointZones_.size())
+ {
+ forAll(frozenPointZones_, i)
+ {
+ const labelList indices
+ (
+ mesh().pointZones().findIndices(frozenPointZones_[i])
+ );
+
+ if (indices.size())
+ {
+ staticPointZones.insert(indices);
+ Info<< " pointZone " << frozenPointZones_[i]
+ << " is frozen (stationary)" << endl;
+ }
+ else
+ {
+ Info<< " frozenZone " << frozenPointZones_[i]
+ << " not found in pointZones" << endl;
+ }
+ }
+ }
+
+ return staticPointZones;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::fvMeshMovers::multiValveEngine::multiValveEngine(fvMesh& mesh)
+:
+ fvMeshMover(mesh),
+ linerPatchSet_(findLinerPatchSet()),
+ slidingPatchSet_(findSlidingPatchSet()),
+ piston_("piston", *this, dict().subDict("piston")),
+ valves_(*this, dict().subOrEmptyDict("valves")),
+ staticPatchSet_(findStaticPatchSet()),
+ frozenPointZones_
+ (
+ dict().lookupOrDefault("frozenZones", wordReList::null())
+ ),
+ linerPatchSet(linerPatchSet_),
+ slidingPatchSet(slidingPatchSet_),
+ piston(piston_),
+ valves(valves_),
+ staticPatchSet(staticPatchSet_)
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
+
+Foam::fvMeshMovers::multiValveEngine::~multiValveEngine()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+Foam::scalar Foam::fvMeshMovers::multiValveEngine::userTime() const
+{
+ return mesh().time().userTimeValue();
+}
+
+
+Foam::scalar Foam::fvMeshMovers::multiValveEngine::userDeltaT() const
+{
+ return mesh().time().timeToUserTime(mesh().time().deltaTValue());
+}
+
+
+bool Foam::fvMeshMovers::multiValveEngine::update()
+{
+ // Accumulate point motion from each moving object into newPoints field.
+ pointField newPoints(mesh().points());
+
+ Info<< "Piston: " << nl;
+
+ piston_.updatePoints(newPoints);
+
+ Info<< " position from TDC: " << piston_.position() << " m" << nl
+ << " displacement: " << piston_.displacement() << " m" << nl
+ << " speed = " << piston_.speed() << " m/s" << nl
+ << " clearance: " << piston_.clearance() << " m" << endl;
+
+ forAll(valves_, valvei)
+ {
+ valveObject& valve = valves_[valvei];
+
+ Info<< "Valve " << valve.name << nl;
+
+ valve.updatePoints(newPoints);
+
+ Info<< " lift: " << (valve.isOpen() ? valve.lift() : 0.0) << " m "
+ << (valve.isOpen() ? "(open)" : "(closed)") << nl
+ << " speed: " << valve.speed() << " m/s" << nl
+ << " displacement: " << valve.displacement() << " m" << endl;
+ }
+
+ // Update the mesh according to the newPoints field.
+ mesh().movePoints(newPoints);
+
+ return true;
+}
+
+
+void Foam::fvMeshMovers::multiValveEngine::topoChange(const polyTopoChangeMap&)
+{
+ NotImplemented;
+}
+
+
+void Foam::fvMeshMovers::multiValveEngine::mapMesh(const polyMeshMap& map)
+{
+ slidingPatchSet_ = findSlidingPatchSet();
+ linerPatchSet_ = findLinerPatchSet();
+ staticPatchSet_ = findStaticPatchSet();
+
+ piston_.mapMesh(map);
+
+ forAll(valves_, valvei)
+ {
+ valves_[valvei].mapMesh(map);
+ }
+}
+
+
+void Foam::fvMeshMovers::multiValveEngine::distribute
+(
+ const polyDistributionMap&
+)
+{
+ NotImplemented;
+}
+
+
+// ************************************************************************* //
diff --git a/src/fvMeshMovers/multiValveEngine/multiValveEngine.H b/src/fvMeshMovers/multiValveEngine/multiValveEngine.H
new file mode 100644
index 0000000000..f1f1d5633a
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/multiValveEngine.H
@@ -0,0 +1,632 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+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 .
+
+Class
+ Foam::fvMeshMovers::multiValveEngine
+
+Description
+ A mesh mover using explicit node translation based on scaled distance
+ functions per moving object. The mover supports any number of valves
+ together with piston motion and following features:
+
+ - Piston motion: Function1 of user-time, may be set to
+ crankConnectingRodMotion for standard crank and connecting rod motion.
+
+ - Valve motion: Function1, may be set to table if the valve lift date is
+ provided in the form of a table.
+
+ - Smooth mesh motion between a moving object and other patches.
+
+ - linerPatches: the set of patches corresponding to the cylinder liner
+ Used by createEngineZones
+
+ - slidingPatches: a set of patches along which mesh is allowed
+ to deform. For example, on the cylinder liner, it is desired to
+ slide mesh nodes while piston is moving.
+
+ - frozenZones: list of pointZones the points of which are frozen,
+ i.e. do not move.
+
+ - Run-time clearance estimation based on patch-to-patch distances printed.
+
+ - Supports cellSet and cellZone definitions to restrict mesh motion.
+
+ - Supports domains with nonConformalCoupling (NCC) interfaces,
+ enabling e.g. nodes to slide along with the interface.
+
+ - Closing the valve can be achieved by meshToMesh mapping onto a new
+ grid with closed valve geometry at user given time.
+
+ - Mesh motion can be controlled per moving object by setting:
+
+ - patches: list of patches defining the object.
+
+ - motion: a Function1 which returns the object position
+ as a function of time.
+
+ - movingZones: list of pointZones the points of which move with the
+ object.
+
+ - maxMotionDistance: a distance away from the moving object
+ after nodes are not allowed to move. (Default inf.)
+
+ - movingFrozenLayerThickness: thickness of layer in which points move
+ with the moving object. (Default 0)
+
+ - staticFrozenLayerThickness: thickness of layer in which points
+ are fixed with respect to static patches (e.g. walls). (Default 0)
+
+ - cosineScaling: a switch whether nodal translation is weighted by
+ its distance from the moving object. The objective is to yield less
+ deformation near the moving object and sustain e.g. boundary layer.
+ (Default no, i.e. linear weighting)
+
+ - fractionalTravelInterval: fraction of the stroke travelled after
+ which the cached motion scaling weights are recalculated
+
+ For valve object only:
+
+ - minLift: a minimum valve lift value after considered closed.
+
+
+ Some of the above parameters are highlighted in a given schematic
+ piston-valve configuration w.r.t entries used to control piston motion.
+ Furthermore, an example dictionary entries are provided below.
+
+ | | | |
+ | | | |
+ | | S | |
+ | | T | |
+ | | E | |
+ | | M | |
+ / | | \
+ / | | \
+ / | | \
+ _____________/ | | \_____________
+ | : | | : |
+ | : /``````````````` ```````````````\ : |
+ | : / VALVE HEAD \ : |
+ | L : /_____________________________________________\ : |
+ | I : /\ : |
+ | N : || staticFrozenLayerThickness : |
+ | E : NCC (optional) \/ (w.r.t. piston motion) : |
+ | R : `````````` : |
+ | : : |
+ | : : |
+ |........:.......................................................:........|
+ | : /\ : |
+ | : || movingFrozenLayerThickness : |
+ |________:_________________________\/____________________________:________|
+ PISTON
+
+ \verbatim
+ mover
+ {
+ type multiValveEngine;
+ libs ("libfvMeshMoversMultiValveEngine.so");
+
+ frozenZones (frozenZone1 frozenZone2);
+
+ slidingPatches
+ (
+ liner
+ valveStem
+ "nonCouple.*"
+ );
+
+ linerPatches (liner);
+
+ piston
+ {
+ patches (piston);
+ axis (0 0 1);
+
+ motion
+ {
+ type crankConnectingRodMotion;
+
+ conRodLength 1e3;
+ stroke 1.0;
+ }
+
+ // Move the points in the piston bowl with the piston
+ movingZones (pistonBowl);
+
+ // Optional
+ maxMotionDistance 1e30;
+ movingFrozenLayerThickness 0;
+ staticFrozenLayerThickness 0;
+
+ fractionalTravelInterval 0.1;
+
+ cosineScaling yes;
+ }
+
+ valves
+ {
+ iv
+ {
+ patches (valveHead);
+ axis (0 0 1);
+
+ // Optional
+ maxMotionDistance 1e30;
+ movingFrozenLayerThickness 0;
+ staticFrozenLayerThickness 0;
+
+ fractionalTravelInterval 0.1;
+
+ cosineScaling yes;
+
+ minLift 0.001;
+
+ motion
+ {
+ type table;
+ values
+ (
+ (0 0)
+ (480 0.1)
+ (720 0)
+ );
+ // For multi-cycle simulations, use repeat
+ outOfBounds repeat;
+ interpolationScheme linear;
+ }
+ }
+ }
+ }
+ \endverbatim
+
+ Note:
+ The implementation utilises pointDist objects for distance computation,
+ resulting distance fields do not propagate through NCC interfaces. Hence,
+ there should be no horizontal NCC interface separating piston from
+ cylinder head as it would result in potentially ill defined mesh
+ deformation. Due to same feature, in a schematic case setup above, valve
+ motion affects only cells between NCC patches even though no cellSet is
+ explicitly defined.
+
+SourceFiles
+ multiValveEngine.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef multiValveEngine_H
+#define multiValveEngine_H
+
+#include "fvMeshMover.H"
+#include "Function1.H"
+#include "pointFields.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declaration of classes
+class pointDist;
+
+namespace fvMeshMovers
+{
+
+/*---------------------------------------------------------------------------*\
+ Class multiValveEngine Declaration
+\*---------------------------------------------------------------------------*/
+
+class multiValveEngine
+:
+ public fvMeshMover
+{
+public:
+
+ class movingObject
+ {
+ friend class multiValveEngine;
+
+ protected:
+
+ // Protected member data
+
+ //- Coefficients dictionary
+ dictionary dict_;
+
+
+ // Protected Data
+
+ //- Reference to engine mesh mover
+ const multiValveEngine& meshMover_;
+
+ public:
+
+ //- Name of the object
+ const word name;
+
+ //- Axis
+ const vector axis;
+
+
+ protected:
+
+ // Protected member data
+
+ //- Piston motion function
+ autoPtr> motion_;
+
+ //- Maximum travel of the object
+ scalar travel_;
+
+ //- Object patchSet
+ labelHashSet patchSet_;
+
+ //- Patches which must not deform during mesh motion
+ labelHashSet staticPatchSet_;
+
+ //- Distance from object beyond which the mesh does not deform
+ scalar maxMotionDistance_;
+
+ //- Distance from object within mesh nodes move
+ // along with the patch
+ scalar movingFrozenLayerThickness_;
+
+ //- Distance from static wall patch at domain perimeter
+ // within mesh nodes do not move
+ scalar staticFrozenLayerThickness_;
+
+ wordReList movingPointZones_;
+
+ //- Points to move when cell zone is supplied
+ labelList pointIDs_;
+
+ //- Interpolation scale (1 at moving patches, 0 at far-field)
+ pointScalarField scale_;
+
+ //- Switch to use cosine-based scaling
+ // for the boundary point motion
+ Switch cosine_;
+
+ //- Update the scale_ field when the normalised travel exceeds
+ // fractionalTravelInterval_
+ const scalar fractionalTravelInterval_;
+
+ //- Count of the scale_ field updates
+ mutable label executionCount_;
+
+ //- Position at last scale update
+ mutable scalar position0_;
+
+
+ // Protected Member Functions
+
+ //- Scale the mesh point deformation with distance functions
+ // w.r.t. moving patches, static patches and a frozen zones.
+ void calcScale
+ (
+ const pointMesh& pMesh,
+ const scalarField& pDistMoving,
+ const scalarField& pDistStatic,
+ scalar dMoving,
+ scalar dMax,
+ scalar dStatic
+ );
+
+ void transformPoints
+ (
+ pointField& newPoints,
+ const vector& translationVector
+ );
+
+ //- Generate staticPatchSet_ based on patch entries
+ void createStaticPatchSet();
+
+ //- Patch-set construction
+ void initPatchSets();
+
+ labelHashSet movingPointZones() const;
+
+
+ public:
+
+ //- Object patchSet
+ const labelHashSet& patchSet;
+
+ // Constructors
+
+ //- Construct from dictionary
+ movingObject
+ (
+ const word& name,
+ const multiValveEngine& engine,
+ const dictionary& dict
+ );
+
+ //- Destructor
+ virtual ~movingObject()
+ {}
+
+
+ // Member Functions
+
+ //- Update from another mesh using the given map
+ virtual void mapMesh(const polyMeshMap&);
+ };
+
+
+ class pistonObject
+ :
+ public movingObject
+ {
+ // Private member data
+
+ //- Bore
+ scalar bore_;
+
+ //- Clearance
+ scalar clearance_;
+
+
+ // Private member functions
+
+ //- Return the bore
+ // calculated from the lateral extent of the piston
+ scalar bore() const;
+
+ //- Calculate clearance estimate based on minimum distance
+ // between piston and any other patch excluding slidingPatches.
+ void correctClearance(pointDist&);
+
+
+ public:
+
+ //- Name of the piston bowl pointZone
+ static word pistonBowlName;
+
+ // Constructors
+
+ //- Construct from dictionary
+ pistonObject
+ (
+ const word& name,
+ const multiValveEngine& engine,
+ const dictionary& dict
+ );
+
+
+ // Member Functions
+
+ //- Return the piston position for the given CA theta
+ scalar position(const scalar theta) const;
+
+ //- Return the current piston position
+ scalar position() const;
+
+ //- Return piston displacement for current time-step
+ scalar displacement() const;
+
+ //- Return piston position for current time-step
+ scalar speed() const;
+
+ //- Return clearance estimate
+ scalar clearance() const;
+
+ //- update points due to piston motion
+ void updatePoints(pointField&);
+
+ //- Update from another mesh using the given map
+ virtual void mapMesh(const polyMeshMap&);
+ };
+
+
+ class valveObject
+ :
+ public movingObject
+ {
+ // Private member data
+
+ //- Minimum valve lift.
+ // On this lift the valve is considered closed
+ const scalar minLift_;
+
+
+ // Private member functions
+
+
+ public:
+
+ // Constructors
+
+ //- Construct from dictionary
+ valveObject
+ (
+ const word& name,
+ const multiValveEngine& engine,
+ const dictionary& dict
+ );
+
+ //- Dummy clone function for PtrList
+ autoPtr clone() const
+ {
+ NotImplemented;
+ return autoPtr(nullptr);
+ }
+
+
+ // Member Functions
+
+ // Valve position and velocity
+
+ //- Return valve position for the given time
+ scalar lift(const scalar theta) const;
+
+ //- Return current valve position
+ scalar lift() const;
+
+ //- Return current valve speed
+ scalar speed() const;
+
+ //- Return valve displacement for current time-step
+ scalar displacement() const;
+
+ //- Is the valve open?
+ bool isOpen() const;
+
+
+ //- update points due to valve motion
+ void updatePoints(pointField&);
+ };
+
+
+ class valveList
+ :
+ public PtrList
+ {
+ public:
+
+ // Constructors
+
+ //- Construct from Istream
+ valveList
+ (
+ const multiValveEngine& engine,
+ const dictionary& dict
+ );
+ };
+
+
+ friend class movingObject;
+ friend class pistonObject;
+ friend class valveObject;
+
+
+private:
+
+ // Private member data
+
+ //- User-defined liner patches
+ labelHashSet linerPatchSet_;
+
+ //- User-defined patches which the mesh can slide along
+ labelHashSet slidingPatchSet_;
+
+ //- Piston object
+ pistonObject piston_;
+
+ //- Container for all valves
+ valveList valves_;
+
+ //- Static patch set
+ labelHashSet staticPatchSet_;
+
+ wordReList frozenPointZones_;
+
+
+ // Private member functions
+
+ //- Lookup and return the liner patch set
+ labelHashSet findLinerPatchSet() const;
+
+ //- Lookup and return the sliding patch set
+ labelHashSet findSlidingPatchSet();
+
+ //- Find and return the static patch set
+ labelHashSet findStaticPatchSet();
+
+ labelHashSet staticPointZones() const;
+
+
+public:
+
+ //- Runtime type information
+ TypeName("multiValveEngine");
+
+ //- Name of the cylinder head pointZone
+ static word cylinderHeadName;
+
+ // Constant access to member data
+
+ //- User-defined liner patches
+ const labelHashSet& linerPatchSet;
+
+ //- User-defined patches which the mesh can slide along
+ const labelHashSet& slidingPatchSet;
+
+ //- Piston object
+ const pistonObject& piston;
+
+ //- Container for all valves
+ const valveList& valves;
+
+ //- Static patch set
+ const labelHashSet& staticPatchSet;
+
+
+ // Constructors
+
+ //- Construct from fvMesh
+ multiValveEngine(fvMesh& mesh);
+
+ //- Disallow default bitwise copy construction
+ multiValveEngine(const multiValveEngine&) = delete;
+
+
+ //- Destructor
+ ~multiValveEngine();
+
+
+ // Member Functions
+
+ //- Return current user-time, CAD, s or ...
+ scalar userTime() const;
+
+ //- Return current user-time-step, CAD, s, ...
+ scalar userDeltaT() const;
+
+ //- Update the mesh for both mesh motion and topology change
+ virtual bool update();
+
+ //- Update corresponding to the given map
+ virtual void topoChange(const polyTopoChangeMap&);
+
+ //- Update from another mesh using the given map
+ virtual void mapMesh(const polyMeshMap&);
+
+ //- Update corresponding to the given distribution map
+ virtual void distribute(const polyDistributionMap&);
+
+
+ // Member Operators
+
+ //- Disallow default bitwise assignment
+ void operator=(const multiValveEngine&) = delete;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+} // End namespace fvMeshMovers
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fvMeshMovers/multiValveEngine/piston.C b/src/fvMeshMovers/multiValveEngine/piston.C
new file mode 100644
index 0000000000..ef76ddb992
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/piston.C
@@ -0,0 +1,220 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+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 "multiValveEngine.H"
+#include "pointDist.H"
+
+/* * * * * * * * * * * * * Static Private Member Data * * * * * * * * * * * */
+
+Foam::word Foam::fvMeshMovers::multiValveEngine::pistonObject::pistonBowlName
+(
+ "pistonBowl"
+);
+
+
+// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
+
+Foam::scalar Foam::fvMeshMovers::multiValveEngine::pistonObject::bore() const
+{
+ const polyBoundaryMesh& pbm = meshMover_.mesh().boundaryMesh();
+
+ // Find the maximum and minimum coordinates of the piston patch-set
+ vector pistonMax(vector::min);
+ vector pistonMin(vector::max);
+
+ forAllConstIter(labelHashSet, patchSet, iter)
+ {
+ const label patchi = iter.key();
+ if (pbm[patchi].localPoints().size())
+ {
+ pistonMax = max(pistonMax, max(pbm[patchi].localPoints()));
+ pistonMin = min(pistonMin, min(pbm[patchi].localPoints()));
+ }
+ }
+
+ reduce(pistonMax, maxOp());
+ reduce(pistonMin, minOp());
+
+ // Assuming the piston moves in the positive axis direction
+ // remove the axis_ component to find the lateral extent of the piston
+ return mag
+ (
+ (pistonMax - (axis& pistonMax)*pistonMax)
+ - (pistonMin - (axis& pistonMin)*pistonMin)
+ )/sqrt(2.0);
+}
+
+
+void Foam::fvMeshMovers::multiValveEngine::pistonObject::correctClearance
+(
+ pointDist& pDist
+)
+{
+ clearance_ = great;
+
+ forAllConstIter(labelHashSet, staticPatchSet_, iter)
+ {
+ const polyPatch& pp = meshMover_.mesh().boundaryMesh()[iter.key()];
+ const labelList& meshPoints = pp.meshPoints();
+
+ forAll(meshPoints, pointi)
+ {
+ clearance_ = min(clearance_, pDist[meshPoints[pointi]]);
+ }
+ }
+
+ reduce(clearance_, minOp());
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::fvMeshMovers::multiValveEngine::pistonObject::pistonObject
+(
+ const word& name,
+ const multiValveEngine& engine,
+ const dictionary& dict
+)
+:
+ movingObject(name, engine, dict),
+ bore_(bore()),
+ clearance_(great)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+Foam::scalar Foam::fvMeshMovers::multiValveEngine::pistonObject::position
+(
+ const scalar theta
+) const
+{
+ return motion_->value(theta);
+}
+
+
+Foam::scalar
+Foam::fvMeshMovers::multiValveEngine::pistonObject::position() const
+{
+ return position(meshMover_.userTime());
+}
+
+
+Foam::scalar
+Foam::fvMeshMovers::multiValveEngine::pistonObject::displacement() const
+{
+ return
+ position(meshMover_.userTime() - meshMover_.userDeltaT())
+ - position();
+}
+
+
+Foam::scalar Foam::fvMeshMovers::multiValveEngine::pistonObject::speed() const
+{
+ return displacement()/(meshMover_.mesh().time().deltaTValue() + vSmall);
+}
+
+
+Foam::scalar
+Foam::fvMeshMovers::multiValveEngine::pistonObject::clearance() const
+{
+ if (mag(position() - position0_)/travel_ > fractionalTravelInterval_)
+ {
+ return clearance_;
+ }
+ else
+ {
+ // Note, valve movement is not considered as valveSet may include
+ // other valves than ones related to ports. Furthermore, this value
+ // is only an estimate and updated rather frequently anyway.
+ return clearance_ - displacement();
+ }
+}
+
+
+void Foam::fvMeshMovers::multiValveEngine::pistonObject::updatePoints
+(
+ pointField& newPoints
+)
+{
+ const scalar position = this->position();
+
+ // Update a cached scale_ field if needed
+ if (mag(position - position0_)/travel_ > fractionalTravelInterval_)
+ {
+ Info << " Updating scale field" << endl;
+
+ const pointMesh& pMesh = pointMesh::New(meshMover_.mesh());
+ const pointField& points(meshMover_.mesh().points());
+
+ pointDist pDistMoving
+ (
+ pMesh,
+ patchSet,
+ movingPointZones(),
+ points,
+ maxMotionDistance_
+ );
+
+ pointDist pDistStatic
+ (
+ pMesh,
+ staticPatchSet_,
+ meshMover_.staticPointZones(),
+ points,
+ maxMotionDistance_
+ );
+
+ // Update the clearance from the distance to piston field
+ correctClearance(pDistMoving);
+
+ calcScale
+ (
+ pMesh,
+ pDistMoving,
+ pDistStatic,
+ movingFrozenLayerThickness_,
+ maxMotionDistance_,
+ staticFrozenLayerThickness_
+ );
+
+ position0_ = position;
+ }
+
+ const vector translationVector(displacement()*axis);
+ transformPoints(newPoints, translationVector);
+}
+
+
+void Foam::fvMeshMovers::multiValveEngine::pistonObject::mapMesh
+(
+ const polyMeshMap& map
+)
+{
+ movingObject::mapMesh(map);
+}
+
+
+// ************************************************************************* //
diff --git a/src/fvMeshMovers/multiValveEngine/pistonPointEdgeData/pistonPointEdgeData.C b/src/fvMeshMovers/multiValveEngine/pistonPointEdgeData/pistonPointEdgeData.C
new file mode 100644
index 0000000000..40cbbf924e
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/pistonPointEdgeData/pistonPointEdgeData.C
@@ -0,0 +1,50 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+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 "pistonPointEdgeData.H"
+
+// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
+
+Foam::Ostream& Foam::operator<<
+(
+ Foam::Ostream& os,
+ const Foam::pistonPointEdgeData& wDist
+)
+{
+ return os << wDist.visited_ << " " << wDist.inBowl();
+}
+
+
+Foam::Istream& Foam::operator>>
+(
+ Foam::Istream& is,
+ Foam::pistonPointEdgeData& wDist
+)
+{
+ return is >> wDist.visited_ >> wDist.inBowl_;
+}
+
+
+// ************************************************************************* //
diff --git a/src/fvMeshMovers/multiValveEngine/pistonPointEdgeData/pistonPointEdgeData.H b/src/fvMeshMovers/multiValveEngine/pistonPointEdgeData/pistonPointEdgeData.H
new file mode 100644
index 0000000000..3ee8f89185
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/pistonPointEdgeData/pistonPointEdgeData.H
@@ -0,0 +1,217 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+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 .
+
+Class
+ Foam::pistonPointEdgeData
+
+Description
+ Holds information regarding nearest wall point. Used in PointEdgeWave.
+ (so not standard FaceCellWave)
+ To be used in wall distance calculation.
+
+SourceFiles
+ pistonPointEdgeDataI.H
+ pistonPointEdgeData.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef pistonPointEdgeData_H
+#define pistonPointEdgeData_H
+
+#include "pointField.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declaration of classes
+class polyPatch;
+class polyMesh;
+class transformer;
+
+
+// Forward declaration of friend functions and operators
+
+class pistonPointEdgeData;
+
+Istream& operator>>(Istream&, pistonPointEdgeData&);
+Ostream& operator<<(Ostream&, const pistonPointEdgeData&);
+
+
+/*---------------------------------------------------------------------------*\
+ Class pistonPointEdgeData Declaration
+\*---------------------------------------------------------------------------*/
+
+class pistonPointEdgeData
+{
+ // Private Data
+
+ //- Has this point or edge been visited
+ bool visited_;
+
+ //- Is this point in the bowl
+ bool inBowl_;
+
+
+public:
+
+ //- Class used to pass data into container
+ class trackingData
+ {
+ public:
+ const pointField& points_;
+ const vector axis_;
+ const scalar maxZ_;
+
+ trackingData
+ (
+ const pointField& points,
+ const vector& axis,
+ const scalar maxZ
+ )
+ :
+ points_(points),
+ axis_(axis),
+ maxZ_(maxZ)
+ {}
+ };
+
+
+private:
+
+ // Private Member Functions
+
+ //- Update visited and inBowl
+ inline bool update(const point&, trackingData& td);
+
+
+public:
+
+ // Constructors
+
+ //- Construct null
+ inline pistonPointEdgeData();
+
+ //- Construct from inBowl
+ inline pistonPointEdgeData(const bool inBowl);
+
+
+ // Member Functions
+
+ // Access
+
+ inline bool inBowl() const;
+
+
+ // Needed by PointEdgeWave
+
+ //- Check whether origin has been changed at all or
+ // still contains original (invalid) value.
+ inline bool valid(trackingData& td) const;
+
+ //- Transform across an interface
+ inline void transform
+ (
+ const polyPatch& patch,
+ const label patchFacei,
+ const transformer& transform,
+ trackingData& td
+ );
+
+ //- Influence of edge on point
+ inline bool updatePoint
+ (
+ const polyMesh& mesh,
+ const label pointi,
+ const label edgei,
+ const pistonPointEdgeData& edgeinfo,
+ const scalar tol,
+ trackingData& td
+ );
+
+ //- Influence of different value on same point.
+ // Merge new and old info.
+ inline bool updatePoint
+ (
+ const polyMesh& mesh,
+ const label pointi,
+ const pistonPointEdgeData& newPointInfo,
+ const scalar tol,
+ trackingData& td
+ );
+
+ //- Influence of point on edge.
+ inline bool updateEdge
+ (
+ const polyMesh& mesh,
+ const label edgei,
+ const label pointi,
+ const pistonPointEdgeData& pointInfo,
+ const scalar tol,
+ trackingData& td
+ );
+
+ //- Equivalent to operator== with trackingData
+ inline bool equal
+ (
+ const pistonPointEdgeData&,
+ trackingData& td
+ ) const;
+
+
+ // Member Operators
+
+ // Needed for List IO
+ inline bool operator==(const pistonPointEdgeData&) const;
+ inline bool operator!=(const pistonPointEdgeData&) const;
+
+
+ // IOstream Operators
+
+ friend Ostream& operator<<(Ostream&, const pistonPointEdgeData&);
+ friend Istream& operator>>(Istream&, pistonPointEdgeData&);
+};
+
+
+//- Data associated with pistonPointEdgeData type are contiguous
+template<>
+inline bool contiguous()
+{
+ return true;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "pistonPointEdgeDataI.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/fvMeshMovers/multiValveEngine/pistonPointEdgeData/pistonPointEdgeDataI.H b/src/fvMeshMovers/multiValveEngine/pistonPointEdgeData/pistonPointEdgeDataI.H
new file mode 100644
index 0000000000..cf16aa21b3
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/pistonPointEdgeData/pistonPointEdgeDataI.H
@@ -0,0 +1,155 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+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 .
+
+\*---------------------------------------------------------------------------*/
+
+// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
+
+inline bool Foam::pistonPointEdgeData::update
+(
+ const point& pt,
+ trackingData& td
+)
+{
+ inBowl_ = (td.axis_& pt) < td.maxZ_;
+ const bool propagate = !visited_ && inBowl_;
+ visited_ = true;
+ return propagate;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+inline Foam::pistonPointEdgeData::pistonPointEdgeData()
+:
+ visited_(false),
+ inBowl_(false)
+{}
+
+
+inline Foam::pistonPointEdgeData::pistonPointEdgeData(const bool inBowl)
+:
+ visited_(true),
+ inBowl_(inBowl)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+inline bool Foam::pistonPointEdgeData::inBowl() const
+{
+ return inBowl_;
+}
+
+
+inline bool Foam::pistonPointEdgeData::valid(trackingData& td) const
+{
+ return visited_;
+}
+
+
+inline void Foam::pistonPointEdgeData::transform
+(
+ const polyPatch& patch,
+ const label patchFacei,
+ const transformer& transform,
+ trackingData& td
+)
+{}
+
+
+inline bool Foam::pistonPointEdgeData::updatePoint
+(
+ const polyMesh& mesh,
+ const label pointi,
+ const label edgei,
+ const pistonPointEdgeData& edgeInfo,
+ const scalar tol,
+ trackingData& td
+)
+{
+ return update(td.points_[pointi], td);
+}
+
+
+inline bool Foam::pistonPointEdgeData::updatePoint
+(
+ const polyMesh& mesh,
+ const label pointi,
+ const pistonPointEdgeData& newPointInfo,
+ const scalar tol,
+ trackingData& td
+)
+{
+ return update(td.points_[pointi], td);
+}
+
+
+inline bool Foam::pistonPointEdgeData::updateEdge
+(
+ const polyMesh& mesh,
+ const label edgei,
+ const label pointi,
+ const pistonPointEdgeData& pointInfo,
+ const scalar tol,
+ trackingData& td
+)
+{
+ visited_ = true;
+ return true;
+}
+
+
+inline bool Foam::pistonPointEdgeData::equal
+(
+ const pistonPointEdgeData& rhs,
+ trackingData& td
+) const
+{
+ return operator==(rhs);
+}
+
+
+// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
+
+inline bool Foam::pistonPointEdgeData::operator==
+(
+ const Foam::pistonPointEdgeData& rhs
+)
+const
+{
+ return visited_ == rhs.visited_ && inBowl_ == rhs.inBowl_;
+}
+
+
+inline bool Foam::pistonPointEdgeData::operator!=
+(
+ const Foam::pistonPointEdgeData& rhs
+)
+const
+{
+ return !(*this == rhs);
+}
+
+
+// ************************************************************************* //
diff --git a/src/fvMeshMovers/multiValveEngine/valve.C b/src/fvMeshMovers/multiValveEngine/valve.C
new file mode 100644
index 0000000000..00577a3b64
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/valve.C
@@ -0,0 +1,146 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+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 "multiValveEngine.H"
+#include "pointDist.H"
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::fvMeshMovers::multiValveEngine::valveObject::valveObject
+(
+ const word& name,
+ const multiValveEngine& engine,
+ const dictionary& dict
+)
+:
+ movingObject(name, engine, dict),
+ minLift_(dict.lookup("minLift"))
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+Foam::scalar Foam::fvMeshMovers::multiValveEngine::valveObject::lift
+(
+ const scalar theta
+) const
+{
+ return motion_->value(theta);
+}
+
+
+bool Foam::fvMeshMovers::multiValveEngine::valveObject::isOpen() const
+{
+ return lift(meshMover_.userTime()) >= minLift_;
+}
+
+
+Foam::scalar Foam::fvMeshMovers::multiValveEngine::valveObject::lift() const
+{
+ return max
+ (
+ lift(meshMover_.userTime()),
+ minLift_
+ );
+}
+
+
+Foam::scalar Foam::fvMeshMovers::multiValveEngine::valveObject::speed() const
+{
+ return
+ -(
+ lift()
+ - max
+ (
+ lift(meshMover_.userTime() - meshMover_.userDeltaT()),
+ minLift_
+ )
+ )/(meshMover_.mesh().time().deltaTValue() + vSmall);
+}
+
+
+Foam::scalar
+Foam::fvMeshMovers::multiValveEngine::valveObject::displacement() const
+{
+ return
+ lift(meshMover_.userTime() - meshMover_.userDeltaT())
+ - lift(meshMover_.userTime());
+}
+
+
+void Foam::fvMeshMovers::multiValveEngine::valveObject::updatePoints
+(
+ pointField& newPoints
+)
+{
+ // Update points only if valve is moving
+ if (isOpen())
+ {
+ const scalar position = this->lift();
+
+ // Update a cached scale_ field if needed
+ if (mag(position - position0_)/travel_ > fractionalTravelInterval_)
+ {
+ const pointMesh& pMesh = pointMesh::New(meshMover_.mesh());
+ const pointField& points(meshMover_.mesh().points());
+
+ const pointDist pDistMoving
+ (
+ pMesh,
+ patchSet,
+ movingPointZones(),
+ points,
+ maxMotionDistance_
+ );
+
+ const pointDist pDistStatic
+ (
+ pMesh,
+ staticPatchSet_,
+ meshMover_.staticPointZones(),
+ points,
+ maxMotionDistance_
+ );
+
+ calcScale
+ (
+ pMesh,
+ pDistMoving,
+ pDistStatic,
+ movingFrozenLayerThickness_,
+ maxMotionDistance_,
+ staticFrozenLayerThickness_
+ );
+
+ position0_ = position;
+ }
+
+ const vector translationVector(displacement()*axis);
+ transformPoints(newPoints, translationVector);
+ }
+}
+
+
+// ************************************************************************* //
diff --git a/src/fvMeshMovers/multiValveEngine/valveList.C b/src/fvMeshMovers/multiValveEngine/valveList.C
new file mode 100644
index 0000000000..2716f85cdd
--- /dev/null
+++ b/src/fvMeshMovers/multiValveEngine/valveList.C
@@ -0,0 +1,70 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+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 "multiValveEngine.H"
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::fvMeshMovers::multiValveEngine::valveList::valveList
+(
+ const multiValveEngine& engine,
+ const dictionary& dict
+)
+{
+ // Count number of valves
+ label nValves = 0;
+ forAllConstIter(dictionary, dict, iter)
+ {
+ if (iter().isDict())
+ {
+ nValves++;
+ }
+ }
+
+ // Add the valves to the list
+ if (nValves > 0)
+ {
+ PtrList::setSize(nValves);
+
+ label i = 0;
+ forAllConstIter(dictionary, dict, iter)
+ {
+ if (iter().isDict())
+ {
+ const word& name = iter().keyword();
+ const dictionary& valveDict = iter().dict();
+
+ PtrList::set
+ (
+ i++,
+ new valveObject(name, engine, valveDict)
+ );
+ }
+ }
+ }
+}
+
+
+// ************************************************************************* //
diff --git a/tutorials/XiFluid/kivaTest/Allrun b/tutorials/XiFluid/kivaTest/Allrun
index 33555b4809..8217a8e850 100755
--- a/tutorials/XiFluid/kivaTest/Allrun
+++ b/tutorials/XiFluid/kivaTest/Allrun
@@ -9,6 +9,8 @@ application=$(getApplication)
runApplication kivaToFoam -file otape17
+runApplication createEngineZones -cylinderHead -pistonBowl
+
runApplication $application
#------------------------------------------------------------------------------
diff --git a/tutorials/XiFluid/kivaTest/constant/dynamicMeshDict b/tutorials/XiFluid/kivaTest/constant/dynamicMeshDict
index e834aab1dc..3d319dadd1 100644
--- a/tutorials/XiFluid/kivaTest/constant/dynamicMeshDict
+++ b/tutorials/XiFluid/kivaTest/constant/dynamicMeshDict
@@ -16,15 +16,36 @@ FoamFile
mover
{
- type layeredEngine;
- libs ("libfvMeshMovers.so");
+ type multiValveEngine;
- conRodLength 0.147;
- bore 0.092;
- stroke 0.08423;
- clearance 0.00115;
- pistonLayers 0;
+ libs ("libfvMeshMoversMultiValveEngine.so");
+
+ slidingPatches (liner);
+ linerPatches (liner);
+
+ // Freeze the points in the cylinder head
+ frozenZones (cylinderHead);
+
+ piston
+ {
+ patches (piston);
+ axis (0 0 1);
+
+ motion
+ {
+ type crankConnectingRodMotion;
+
+ conRodLength 0.147;
+ stroke 0.08423;
+ }
+
+ // Move the points in the piston bowl with the piston
+ movingZones (pistonBowl);
+
+ // There is no need to update the motion weights
+ fractionalTravelInterval 1;
+ }
}
diff --git a/tutorials/XiFluid/kivaTest/system/controlDict b/tutorials/XiFluid/kivaTest/system/controlDict
index 5e5cc63d80..1ff1e8bf38 100644
--- a/tutorials/XiFluid/kivaTest/system/controlDict
+++ b/tutorials/XiFluid/kivaTest/system/controlDict
@@ -58,4 +58,32 @@ userTime
rpm 1500;
}
+functions
+{
+ setDeltaT
+ {
+ type coded;
+
+ // Load the library containing the 'coded' functionObject
+ libs ("libutilityFunctionObjects.so");
+
+ codeInclude
+ #{
+ #include "volFields.H"
+ #};
+
+ codeExecute
+ #{
+ const Time& runTime = mesh().time();
+ if (runTime.userTimeValue() >= -15.0)
+ {
+ const_cast