multiphase: Rationalised alphaContactAngle handling

Alpha contact angle boundaries are now specified in the following way
for multiphase solvers (i.e., multiphaseInterFoam,
compressibleMultiphaseInterFoam, and multiphaseEulerFoam):

   boundaryField
   {
       wall
       {
           type            alphaContactAngle;
           contactAngleProperties
           {
               water
               {
                   // Constant contact angle
                   theta0 90;
               }
               oil
               {
                   // Dynamic contact angle
                   theta0 90;
                   uTheta 1;
                   thetaA 125;
                   thetaR 85;
               }
           }
           value           uniform 0;
       }
   }

All solvers now share the same implementation of the alphaContactAngle
boundary condition and the contact angle correction algorithm.

If alpha contact angle boundary conditions are used they must be
specified for all phases or an error will result. The consistency of the
input will also be checked. The angles given for water in the alpha.air
file must be 180 degrees minus the angles given for air in the
alpha.water file.
This commit is contained in:
Will Bainbridge
2022-01-28 17:10:17 +00:00
parent ba5612414a
commit ba130ec083
41 changed files with 641 additions and 1281 deletions

View File

@ -1,5 +1,4 @@
phaseModel/phaseModel.C
alphaContactAngle/alphaContactAngleFvPatchScalarField.C
compressibleMultiphaseMixture.C
LIB = $(FOAM_LIBBIN)/libcompressibleMultiphaseMixture

View File

@ -1,11 +1,13 @@
EXE_INC = \
-I$(LIB_SRC)/physicalProperties/lnInclude \
-I$(LIB_SRC)/multiphaseModels/multiphaseProperties/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
LIB_LIBS = \
-lfluidThermophysicalModels \
-lmultiphaseProperties \
-lspecie \
-lfiniteVolume \
-lmeshTools

View File

@ -1,145 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2013-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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "alphaContactAngleFvPatchScalarField.H"
#include "addToRunTimeSelectionTable.H"
#include "fvPatchFieldMapper.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
alphaContactAngleFvPatchScalarField::interfaceThetaProps::interfaceThetaProps
(
Istream& is
)
:
theta0_(readScalar(is)),
uTheta_(readScalar(is)),
thetaA_(readScalar(is)),
thetaR_(readScalar(is))
{}
Istream& operator>>
(
Istream& is,
alphaContactAngleFvPatchScalarField::interfaceThetaProps& tp
)
{
is >> tp.theta0_ >> tp.uTheta_ >> tp.thetaA_ >> tp.thetaR_;
return is;
}
Ostream& operator<<
(
Ostream& os,
const alphaContactAngleFvPatchScalarField::interfaceThetaProps& tp
)
{
os << tp.theta0_ << token::SPACE
<< tp.uTheta_ << token::SPACE
<< tp.thetaA_ << token::SPACE
<< tp.thetaR_;
return os;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
alphaContactAngleFvPatchScalarField::alphaContactAngleFvPatchScalarField
(
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF
)
:
zeroGradientFvPatchScalarField(p, iF)
{}
alphaContactAngleFvPatchScalarField::alphaContactAngleFvPatchScalarField
(
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF,
const dictionary& dict
)
:
zeroGradientFvPatchScalarField(p, iF),
thetaProps_(dict.lookup("thetaProperties"))
{
evaluate();
}
alphaContactAngleFvPatchScalarField::alphaContactAngleFvPatchScalarField
(
const alphaContactAngleFvPatchScalarField& gcpsf,
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
zeroGradientFvPatchScalarField(gcpsf, p, iF, mapper),
thetaProps_(gcpsf.thetaProps_)
{}
alphaContactAngleFvPatchScalarField::alphaContactAngleFvPatchScalarField
(
const alphaContactAngleFvPatchScalarField& gcpsf,
const DimensionedField<scalar, volMesh>& iF
)
:
zeroGradientFvPatchScalarField(gcpsf, iF),
thetaProps_(gcpsf.thetaProps_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void alphaContactAngleFvPatchScalarField::write(Ostream& os) const
{
fvPatchScalarField::write(os);
writeEntry(os, "thetaProperties", thetaProps_);
writeEntry(os, "value", *this);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makePatchTypeField
(
fvPatchScalarField,
alphaContactAngleFvPatchScalarField
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -1,206 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2013-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 <http://www.gnu.org/licenses/>.
Class
Foam::alphaContactAngleFvPatchScalarField
Description
Contact-angle boundary condition for multi-phase interface-capturing
simulations. Used in conjunction with multiphaseMixture.
SourceFiles
alphaContactAngleFvPatchScalarField.C
\*---------------------------------------------------------------------------*/
#ifndef alphaContactAngleFvPatchScalarField_H
#define alphaContactAngleFvPatchScalarField_H
#include "zeroGradientFvPatchFields.H"
#include "compressibleMultiphaseMixture.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class alphaContactAngleFvPatch Declaration
\*---------------------------------------------------------------------------*/
class alphaContactAngleFvPatchScalarField
:
public zeroGradientFvPatchScalarField
{
public:
class interfaceThetaProps
{
//- Equilibrium contact angle
scalar theta0_;
//- Dynamic contact angle velocity scale
scalar uTheta_;
//- Limiting advancing contact angle
scalar thetaA_;
//- Limiting receding contact angle
scalar thetaR_;
public:
// Constructors
interfaceThetaProps()
{}
interfaceThetaProps(Istream&);
// Member Functions
//- Return the equilibrium contact angle theta0
scalar theta0(bool matched=true) const
{
if (matched) return theta0_;
else return 180.0 - theta0_;
}
//- Return the dynamic contact angle velocity scale
scalar uTheta() const
{
return uTheta_;
}
//- Return the limiting advancing contact angle
scalar thetaA(bool matched=true) const
{
if (matched) return thetaA_;
else return 180.0 - thetaA_;
}
//- Return the limiting receding contact angle
scalar thetaR(bool matched=true) const
{
if (matched) return thetaR_;
else return 180.0 - thetaR_;
}
// IO functions
friend Istream& operator>>(Istream&, interfaceThetaProps&);
friend Ostream& operator<<(Ostream&, const interfaceThetaProps&);
};
typedef HashTable
<
interfaceThetaProps,
compressibleMultiphaseMixture::interfacePair,
compressibleMultiphaseMixture::interfacePair::hash
> thetaPropsTable;
private:
// Private Data
thetaPropsTable thetaProps_;
public:
//- Runtime type information
TypeName("alphaContactAngle");
// Constructors
//- Construct from patch and internal field
alphaContactAngleFvPatchScalarField
(
const fvPatch&,
const DimensionedField<scalar, volMesh>&
);
//- Construct from patch, internal field and dictionary
alphaContactAngleFvPatchScalarField
(
const fvPatch&,
const DimensionedField<scalar, volMesh>&,
const dictionary&
);
//- Construct by mapping given alphaContactAngleFvPatchScalarField
// onto a new patch
alphaContactAngleFvPatchScalarField
(
const alphaContactAngleFvPatchScalarField&,
const fvPatch&,
const DimensionedField<scalar, volMesh>&,
const fvPatchFieldMapper&
);
//- Construct as copy setting internal field reference
alphaContactAngleFvPatchScalarField
(
const alphaContactAngleFvPatchScalarField&,
const DimensionedField<scalar, volMesh>&
);
//- Construct and return a clone setting internal field reference
virtual tmp<fvPatchScalarField> clone
(
const DimensionedField<scalar, volMesh>& iF
) const
{
return tmp<fvPatchScalarField>
(
new alphaContactAngleFvPatchScalarField(*this, iF)
);
}
// Member Functions
//- Return the contact angle properties
const thetaPropsTable& thetaProps() const
{
return thetaProps_;
}
//- Write
virtual void write(Ostream&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2013-2021 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2013-2022 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -25,7 +25,7 @@ License
#include "compressibleMultiphaseMixture.H"
#include "alphaContactAngleFvPatchScalarField.H"
#include "unitConversion.H"
#include "correctContactAngle.H"
#include "Time.H"
#include "subCycle.H"
#include "MULES.H"
@ -401,138 +401,6 @@ Foam::tmp<Foam::surfaceScalarField> Foam::compressibleMultiphaseMixture::nHatf
}
// Correction for the boundary condition on the unit normal nHat on
// walls to produce the correct contact angle.
// The dynamic contact angle is calculated from the component of the
// velocity on the direction of the interface, parallel to the wall.
void Foam::compressibleMultiphaseMixture::correctContactAngle
(
const phaseModel& alpha1,
const phaseModel& alpha2,
surfaceVectorField::Boundary& nHatb
) const
{
const volScalarField::Boundary& a1bf = alpha1.boundaryField();
const volScalarField::Boundary& a2bf = alpha2.boundaryField();
const fvBoundaryMesh& boundary = mesh_.boundary();
forAll(boundary, patchi)
{
if
(
isA<alphaContactAngleFvPatchScalarField>(a1bf[patchi])
|| isA<alphaContactAngleFvPatchScalarField>(a2bf[patchi])
)
{
if
(
isA<alphaContactAngleFvPatchScalarField>(a1bf[patchi])
&& isA<alphaContactAngleFvPatchScalarField>(a2bf[patchi])
)
{
FatalErrorInFunction
<< "alphaContactAngle boundary condition "
"specified on patch " << boundary[patchi].name()
<< " for both " << alpha1.name() << " and " << alpha2.name()
<< nl << "which may be inconsistent."
<< exit(FatalError);
}
const alphaContactAngleFvPatchScalarField& acap =
isA<alphaContactAngleFvPatchScalarField>(a1bf[patchi])
? refCast<const alphaContactAngleFvPatchScalarField>(a1bf[patchi])
: refCast<const alphaContactAngleFvPatchScalarField>(a2bf[patchi])
;
vectorField& nHatPatch = nHatb[patchi];
vectorField AfHatPatch
(
mesh_.Sf().boundaryField()[patchi]
/mesh_.magSf().boundaryField()[patchi]
);
alphaContactAngleFvPatchScalarField::thetaPropsTable::
const_iterator tp =
acap.thetaProps().find(interfacePair(alpha1, alpha2));
if (tp == acap.thetaProps().end())
{
FatalErrorInFunction
<< "Cannot find interface " << interfacePair(alpha1, alpha2)
<< "\n in table of theta properties for patch "
<< acap.patch().name()
<< exit(FatalError);
}
const bool matched = (tp.key().first() == alpha1.name());
const scalar theta0 = degToRad(tp().theta0(matched));
scalarField theta(boundary[patchi].size(), theta0);
const scalar uTheta = tp().uTheta();
// Calculate the dynamic contact angle if required
if (uTheta > small)
{
const scalar thetaA = degToRad(tp().thetaA(matched));
const scalar thetaR = degToRad(tp().thetaR(matched));
// Calculated the component of the velocity parallel to the wall
vectorField Uwall
(
U_.boundaryField()[patchi].patchInternalField()
- U_.boundaryField()[patchi]
);
Uwall -= (AfHatPatch & Uwall)*AfHatPatch;
// Find the direction of the interface parallel to the wall
vectorField nWall
(
nHatPatch - (AfHatPatch & nHatPatch)*AfHatPatch
);
// Normalise nWall
nWall /= (mag(nWall) + small);
// Calculate Uwall resolved normal to the interface parallel to
// the interface
const scalarField uwall(nWall & Uwall);
theta += (thetaA - thetaR)*tanh(uwall/uTheta);
}
// Reset nHatPatch to correspond to the contact angle
const scalarField a12(nHatPatch & AfHatPatch);
const scalarField b1(cos(theta));
scalarField b2(nHatPatch.size());
forAll(b2, facei)
{
b2[facei] = cos(acos(a12[facei]) - theta[facei]);
}
const scalarField det(1.0 - a12*a12);
const scalarField a((b1 - a12*b2)/det);
const scalarField b((b2 - a12*b1)/det);
nHatPatch = a*AfHatPatch + b*nHatPatch;
nHatPatch /= (mag(nHatPatch) + deltaN_.value());
}
}
}
Foam::tmp<Foam::volScalarField> Foam::compressibleMultiphaseMixture::K
(
const phaseModel& alpha1,
@ -541,7 +409,14 @@ Foam::tmp<Foam::volScalarField> Foam::compressibleMultiphaseMixture::K
{
tmp<surfaceVectorField> tnHatfv = nHatfv(alpha1, alpha2);
correctContactAngle(alpha1, alpha2, tnHatfv.ref().boundaryFieldRef());
correctContactAngle
(
alpha1,
alpha2,
U_.boundaryField(),
deltaN_,
tnHatfv.ref().boundaryFieldRef()
);
// Simple expression for curvature
return -fvc::div(tnHatfv & mesh_.Sf());

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2013-2021 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2013-2022 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -171,13 +171,6 @@ private:
const volScalarField& alpha2
) const;
void correctContactAngle
(
const phaseModel& alpha1,
const phaseModel& alpha2,
surfaceVectorField::Boundary& nHatb
) const;
tmp<volScalarField> K
(
const phaseModel& alpha1,

View File

@ -19,6 +19,7 @@ EXE_LIBS = \
-leulerianInterfacialCompositionModels \
-lmultiphaseMomentumTransportModels \
-lmultiphaseReactions \
-lmultiphaseProperties \
-lphaseFluidThermophysicalTransportModels \
-lphaseFluidReactionThermophysicalTransportModels \
-lfiniteVolume \

View File

@ -105,6 +105,4 @@ BlendedInterfacialModel/blendingMethods/hyperbolic/hyperbolic.C
BlendedInterfacialModel/blendingMethods/continuous/continuous.C
BlendedInterfacialModel/blendingMethods/segregatedBlendingMethod/segregatedBlendingMethod.C
alphaContactAngle/alphaContactAngleFvPatchScalarField.C
LIB = $(FOAM_LIBBIN)/libphaseSystem

View File

@ -3,6 +3,7 @@ EXE_INC = \
-I../interfacialCompositionModels/lnInclude \
-I../multiphaseCompressibleMomentumTransportModels/lnInclude \
-I$(LIB_SRC)/physicalProperties/lnInclude \
-I$(LIB_SRC)/multiphaseModels/multiphaseProperties/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/reactionThermo/lnInclude \

View File

@ -34,7 +34,7 @@ License
#include "CorrectPhi.H"
#include "fvcMeshPhi.H"
#include "alphaContactAngleFvPatchScalarField.H"
#include "unitConversion.H"
#include "correctContactAngle.H"
#include "dragModel.H"
#include "movingWallVelocityFvPatchVectorField.H"
#include "pimpleControl.H"
@ -184,136 +184,6 @@ Foam::tmp<Foam::surfaceScalarField> Foam::phaseSystem::nHatf
}
void Foam::phaseSystem::correctContactAngle
(
const phaseModel& phase1,
const phaseModel& phase2,
surfaceVectorField::Boundary& nHatbf
) const
{
const volScalarField& a1 = phase1;
const volScalarField& a2 = phase2;
const volScalarField::Boundary& a1bf = a1.boundaryField();
const volScalarField::Boundary& a2bf = a2.boundaryField();
const fvBoundaryMesh& boundary = mesh_.boundary();
forAll(boundary, patchi)
{
const fvPatchScalarField& a1p = a1bf[patchi];
const fvPatchScalarField& a2p = a2bf[patchi];
const bool a1pIsCa = isA<alphaContactAngleFvPatchScalarField>(a1p);
const bool a2pIsCa = isA<alphaContactAngleFvPatchScalarField>(a2p);
if (a1pIsCa || a2pIsCa)
{
if (a1pIsCa != a2pIsCa)
{
FatalErrorInFunction
<< alphaContactAngleFvPatchScalarField::typeName
<< " boundary condition specified on patch "
<< boundary[patchi].name() << " for "
<< (a1pIsCa ? a1.name() : a2.name()) << " but not for "
<< (a2pIsCa ? a1.name() : a2.name())
<< exit(FatalError);
}
const alphaContactAngleFvPatchScalarField& a1ca =
refCast<const alphaContactAngleFvPatchScalarField>(a1p);
const alphaContactAngleFvPatchScalarField& a2ca =
refCast<const alphaContactAngleFvPatchScalarField>(a2p);
const bool a1caHasProps = a1ca.thetaProps().found(phase2.name());
const bool a2caHasProps = a2ca.thetaProps().found(phase1.name());
if (!a1caHasProps && !a2caHasProps)
{
FatalErrorInFunction
<< "Neither "
<< alphaContactAngleFvPatchScalarField::typeName
<< " boundary condition specified on patch "
<< boundary[patchi].name()
<< " for " << a1.name() << " and " << a2.name()
<< " contains properties for the other phase"
<< exit(FatalError);
}
if
(
a1caHasProps && a2caHasProps
&& a1ca.thetaProps()[phase2.name()]
!= a2ca.thetaProps()[phase1.name()].reversed()
)
{
FatalErrorInFunction
<< "The "
<< alphaContactAngleFvPatchScalarField::typeName
<< " boundary conditions specified on patch "
<< boundary[patchi].name()
<< " for " << a1.name() << " and " << a2.name()
<< " contain inconsistent properties"
<< exit(FatalError);
}
const alphaContactAngleFvPatchScalarField::contactAngleProperties
tp = a1caHasProps
? a1ca.thetaProps()[phase2.name()]
: a2ca.thetaProps()[phase1.name()].reversed();
const vectorField np(mesh_.boundary()[patchi].nf());
vectorField& nHatp = nHatbf[patchi];
// Calculate the contact angle
scalarField theta(np.size(), degToRad(tp.theta0()));
// Calculate the dynamic contact angle if required
if (tp.dynamic())
{
const scalar uTheta = tp.uTheta();
const scalar thetaA = degToRad(tp.thetaA());
const scalar thetaR = degToRad(tp.thetaR());
// Calculated the component of the velocity parallel to the wall
vectorField Uwall
(
phase1.U()().boundaryField()[patchi].patchInternalField()
- phase1.U()().boundaryField()[patchi]
);
Uwall -= (np & Uwall)*np;
// Find the direction of the interface parallel to the wall
vectorField nWall(nHatp - (np & nHatp)*np);
nWall /= (mag(nWall) + small);
// Calculate Uwall resolved normal to the interface parallel to
// the interface
const scalarField uwall(nWall & Uwall);
theta += (thetaA - thetaR)*tanh(uwall/uTheta);
}
// Reset nHatp to correspond to the contact angle
const scalarField a12(nHatp & np);
const scalarField b1(cos(theta));
scalarField b2(nHatp.size());
forAll(b2, facei)
{
b2[facei] = cos(acos(a12[facei]) - theta[facei]);
}
const scalarField det(1 - a12*a12);
const scalarField a((b1 - a12*b2)/det);
const scalarField b((b2 - a12*b1)/det);
nHatp = a*np + b*nHatp;
nHatp /= (mag(nHatp) + deltaN_.value());
}
}
}
Foam::tmp<Foam::volScalarField> Foam::phaseSystem::K
(
const phaseModel& phase1,
@ -322,7 +192,14 @@ Foam::tmp<Foam::volScalarField> Foam::phaseSystem::K
{
tmp<surfaceVectorField> tnHatfv = nHatfv(phase1, phase2);
correctContactAngle(phase1, phase2, tnHatfv.ref().boundaryFieldRef());
correctContactAngle
(
phase1,
phase2,
phase1.U()().boundaryField(),
deltaN_,
tnHatfv.ref().boundaryFieldRef()
);
// Simple expression for curvature
return -fvc::div(tnHatfv & mesh_.Sf());

View File

@ -211,19 +211,6 @@ protected:
const volScalarField& alpha2
) const;
//- Correction for the boundary condition on the unit normal nHat on
// walls to produce the correct contact angle.
//
// The dynamic contact angle is calculated from the component of
// the velocity on the direction of the interface, parallel to the
// wall. Used for interface compression.
void correctContactAngle
(
const phaseModel& alpha1,
const phaseModel& alpha2,
surfaceVectorField::Boundary& nHatb
) const;
//- Curvature of interface between two phases
// Used for interface compression
tmp<volScalarField> K

View File

@ -1,5 +1,4 @@
phase/phase.C
alphaContactAngle/alphaContactAngleFvPatchScalarField.C
multiphaseMixture.C
LIB = $(FOAM_LIBBIN)/libmultiphaseInterFoam

View File

@ -1,6 +1,7 @@
EXE_INC = \
-IalphaContactAngle \
-I$(LIB_SRC)/physicalProperties/lnInclude \
-I$(LIB_SRC)/multiphaseModels/multiphaseProperties/lnInclude \
-I$(LIB_SRC)/twoPhaseModels/interfaceProperties/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
@ -8,5 +9,6 @@ EXE_INC = \
LIB_LIBS = \
-linterfaceProperties \
-lphysicalProperties \
-lmultiphaseProperties \
-lfiniteVolume \
-lmeshTools

View File

@ -1,145 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "alphaContactAngleFvPatchScalarField.H"
#include "addToRunTimeSelectionTable.H"
#include "fvPatchFieldMapper.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
alphaContactAngleFvPatchScalarField::interfaceThetaProps::interfaceThetaProps
(
Istream& is
)
:
theta0_(readScalar(is)),
uTheta_(readScalar(is)),
thetaA_(readScalar(is)),
thetaR_(readScalar(is))
{}
Istream& operator>>
(
Istream& is,
alphaContactAngleFvPatchScalarField::interfaceThetaProps& tp
)
{
is >> tp.theta0_ >> tp.uTheta_ >> tp.thetaA_ >> tp.thetaR_;
return is;
}
Ostream& operator<<
(
Ostream& os,
const alphaContactAngleFvPatchScalarField::interfaceThetaProps& tp
)
{
os << tp.theta0_ << token::SPACE
<< tp.uTheta_ << token::SPACE
<< tp.thetaA_ << token::SPACE
<< tp.thetaR_;
return os;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
alphaContactAngleFvPatchScalarField::alphaContactAngleFvPatchScalarField
(
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF
)
:
zeroGradientFvPatchScalarField(p, iF)
{}
alphaContactAngleFvPatchScalarField::alphaContactAngleFvPatchScalarField
(
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF,
const dictionary& dict
)
:
zeroGradientFvPatchScalarField(p, iF),
thetaProps_(dict.lookup("thetaProperties"))
{
evaluate();
}
alphaContactAngleFvPatchScalarField::alphaContactAngleFvPatchScalarField
(
const alphaContactAngleFvPatchScalarField& gcpsf,
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
zeroGradientFvPatchScalarField(gcpsf, p, iF, mapper),
thetaProps_(gcpsf.thetaProps_)
{}
alphaContactAngleFvPatchScalarField::alphaContactAngleFvPatchScalarField
(
const alphaContactAngleFvPatchScalarField& gcpsf,
const DimensionedField<scalar, volMesh>& iF
)
:
zeroGradientFvPatchScalarField(gcpsf, iF),
thetaProps_(gcpsf.thetaProps_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void alphaContactAngleFvPatchScalarField::write(Ostream& os) const
{
fvPatchScalarField::write(os);
writeEntry(os, "thetaProperties", thetaProps_);
writeEntry(os, "value", *this);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makePatchTypeField
(
fvPatchScalarField,
alphaContactAngleFvPatchScalarField
);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -1,206 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2020 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 <http://www.gnu.org/licenses/>.
Class
Foam::alphaContactAngleFvPatchScalarField
Description
Contact-angle boundary condition for multi-phase interface-capturing
simulations. Used in conjunction with multiphaseMixture.
SourceFiles
alphaContactAngleFvPatchScalarField.C
\*---------------------------------------------------------------------------*/
#ifndef alphaContactAngleFvPatchScalarField_H
#define alphaContactAngleFvPatchScalarField_H
#include "zeroGradientFvPatchFields.H"
#include "multiphaseMixture.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class alphaContactAngleFvPatch Declaration
\*---------------------------------------------------------------------------*/
class alphaContactAngleFvPatchScalarField
:
public zeroGradientFvPatchScalarField
{
public:
class interfaceThetaProps
{
//- Equilibrium contact angle
scalar theta0_;
//- Dynamic contact angle velocity scale
scalar uTheta_;
//- Limiting advancing contact angle
scalar thetaA_;
//- Limiting receding contact angle
scalar thetaR_;
public:
// Constructors
interfaceThetaProps()
{}
interfaceThetaProps(Istream&);
// Member Functions
//- Return the equilibrium contact angle theta0
scalar theta0(bool matched=true) const
{
if (matched) return theta0_;
else return 180.0 - theta0_;
}
//- Return the dynamic contact angle velocity scale
scalar uTheta() const
{
return uTheta_;
}
//- Return the limiting advancing contact angle
scalar thetaA(bool matched=true) const
{
if (matched) return thetaA_;
else return 180.0 - thetaA_;
}
//- Return the limiting receding contact angle
scalar thetaR(bool matched=true) const
{
if (matched) return thetaR_;
else return 180.0 - thetaR_;
}
// IO functions
friend Istream& operator>>(Istream&, interfaceThetaProps&);
friend Ostream& operator<<(Ostream&, const interfaceThetaProps&);
};
typedef HashTable
<
interfaceThetaProps,
multiphaseMixture::interfacePair,
multiphaseMixture::interfacePair::hash
> thetaPropsTable;
private:
// Private Data
thetaPropsTable thetaProps_;
public:
//- Runtime type information
TypeName("alphaContactAngle");
// Constructors
//- Construct from patch and internal field
alphaContactAngleFvPatchScalarField
(
const fvPatch&,
const DimensionedField<scalar, volMesh>&
);
//- Construct from patch, internal field and dictionary
alphaContactAngleFvPatchScalarField
(
const fvPatch&,
const DimensionedField<scalar, volMesh>&,
const dictionary&
);
//- Construct by mapping given alphaContactAngleFvPatchScalarField
// onto a new patch
alphaContactAngleFvPatchScalarField
(
const alphaContactAngleFvPatchScalarField&,
const fvPatch&,
const DimensionedField<scalar, volMesh>&,
const fvPatchFieldMapper&
);
//- Construct as copy setting internal field reference
alphaContactAngleFvPatchScalarField
(
const alphaContactAngleFvPatchScalarField&,
const DimensionedField<scalar, volMesh>&
);
//- Construct and return a clone setting internal field reference
virtual tmp<fvPatchScalarField> clone
(
const DimensionedField<scalar, volMesh>& iF
) const
{
return tmp<fvPatchScalarField>
(
new alphaContactAngleFvPatchScalarField(*this, iF)
);
}
// Member Functions
//- Return the contact angle properties
const thetaPropsTable& thetaProps() const
{
return thetaProps_;
}
//- Write
virtual void write(Ostream&) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -25,7 +25,7 @@ License
#include "multiphaseMixture.H"
#include "alphaContactAngleFvPatchScalarField.H"
#include "unitConversion.H"
#include "correctContactAngle.H"
#include "Time.H"
#include "subCycle.H"
#include "MULES.H"
@ -391,132 +391,6 @@ Foam::tmp<Foam::surfaceScalarField> Foam::multiphaseMixture::nHatf
}
void Foam::multiphaseMixture::correctContactAngle
(
const phase& alpha1,
const phase& alpha2,
surfaceVectorField::Boundary& nHatb
) const
{
const volScalarField::Boundary& a1bf = alpha1.boundaryField();
const volScalarField::Boundary& a2bf = alpha2.boundaryField();
const fvBoundaryMesh& boundary = mesh_.boundary();
forAll(boundary, patchi)
{
if
(
isA<alphaContactAngleFvPatchScalarField>(a1bf[patchi])
|| isA<alphaContactAngleFvPatchScalarField>(a2bf[patchi])
)
{
if
(
isA<alphaContactAngleFvPatchScalarField>(a1bf[patchi])
&& isA<alphaContactAngleFvPatchScalarField>(a2bf[patchi])
)
{
FatalErrorInFunction
<< "alphaContactAngle boundary condition "
"specified on patch " << boundary[patchi].name()
<< " for both " << alpha1.name() << " and " << alpha2.name()
<< nl << "which may be inconsistent."
<< exit(FatalError);
}
const alphaContactAngleFvPatchScalarField& acap =
isA<alphaContactAngleFvPatchScalarField>(a1bf[patchi])
? refCast<const alphaContactAngleFvPatchScalarField>(a1bf[patchi])
: refCast<const alphaContactAngleFvPatchScalarField>(a2bf[patchi])
;
vectorField& nHatPatch = nHatb[patchi];
const vectorField AfHatPatch
(
mesh_.Sf().boundaryField()[patchi]
/mesh_.magSf().boundaryField()[patchi]
);
alphaContactAngleFvPatchScalarField::thetaPropsTable::
const_iterator tp =
acap.thetaProps().find(interfacePair(alpha1, alpha2));
if (tp == acap.thetaProps().end())
{
FatalErrorInFunction
<< "Cannot find interface " << interfacePair(alpha1, alpha2)
<< "\n in table of theta properties for patch "
<< acap.patch().name()
<< exit(FatalError);
}
const bool matched = (tp.key().first() == alpha1.name());
const scalar theta0 = degToRad(tp().theta0(matched));
scalarField theta(boundary[patchi].size(), theta0);
const scalar uTheta = tp().uTheta();
// Calculate the dynamic contact angle if required
if (uTheta > small)
{
const scalar thetaA = degToRad(tp().thetaA(matched));
const scalar thetaR = degToRad(tp().thetaR(matched));
// Calculated the component of the velocity parallel to the wall
vectorField Uwall
(
U_.boundaryField()[patchi].patchInternalField()
- U_.boundaryField()[patchi]
);
Uwall -= (AfHatPatch & Uwall)*AfHatPatch;
// Find the direction of the interface parallel to the wall
vectorField nWall
(
nHatPatch - (AfHatPatch & nHatPatch)*AfHatPatch
);
// Normalise nWall
nWall /= (mag(nWall) + small);
// Calculate Uwall resolved normal to the interface parallel to
// the interface
const scalarField uwall(nWall & Uwall);
theta += (thetaA - thetaR)*tanh(uwall/uTheta);
}
// Reset nHatPatch to correspond to the contact angle
const scalarField a12(nHatPatch & AfHatPatch);
const scalarField b1(cos(theta));
scalarField b2(nHatPatch.size());
forAll(b2, facei)
{
b2[facei] = cos(acos(a12[facei]) - theta[facei]);
}
const scalarField det(1.0 - a12*a12);
const scalarField a((b1 - a12*b2)/det);
const scalarField b((b2 - a12*b1)/det);
nHatPatch = a*AfHatPatch + b*nHatPatch;
nHatPatch /= (mag(nHatPatch) + deltaN_.value());
}
}
}
Foam::tmp<Foam::volScalarField> Foam::multiphaseMixture::K
(
const phase& alpha1,
@ -525,7 +399,14 @@ Foam::tmp<Foam::volScalarField> Foam::multiphaseMixture::K
{
tmp<surfaceVectorField> tnHatfv = nHatfv(alpha1, alpha2);
correctContactAngle(alpha1, alpha2, tnHatfv.ref().boundaryFieldRef());
correctContactAngle
(
alpha1,
alpha2,
U_.boundaryField(),
deltaN_,
tnHatfv.ref().boundaryFieldRef()
);
// Simple expression for curvature
return -fvc::div(tnHatfv & mesh_.Sf());

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2022 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -173,18 +173,6 @@ private:
const volScalarField& alpha2
) const;
//- Correction for the boundary condition on the unit normal nHat on
// walls to produce the correct contact angle.
//
// The dynamic contact angle is calculated from the component of the
// velocity on the direction of the interface, parallel to the wall.
void correctContactAngle
(
const phase& alpha1,
const phase& alpha2,
surfaceVectorField::Boundary& nHatb
) const;
tmp<volScalarField> K(const phase& alpha1, const phase& alpha2) const;

View File

@ -59,6 +59,7 @@ wmake $targetType physicalProperties
thermophysicalModels/Allwmake $targetType $*
twoPhaseModels/Allwmake $targetType $*
multiphaseModels/Allwmake $targetType $*
MomentumTransportModels/Allwmake $targetType $*
ThermophysicalTransportModels/Allwmake $targetType $*
wmake $targetType radiationModels

9
src/multiphaseModels/Allwmake Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
# Parse arguments for library compilation
. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments
wmake $targetType multiphaseProperties
#------------------------------------------------------------------------------

View File

@ -0,0 +1,4 @@
alphaContactAngle/alphaContactAngleFvPatchScalarField.C
correctContactAngle/correctContactAngle.C
LIB = $(FOAM_LIBBIN)/libmultiphaseProperties

View File

@ -0,0 +1,5 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude
LIB_LIBS = \
-lfiniteVolume

View File

@ -26,7 +26,7 @@ Class
Description
Contact-angle boundary condition for multi-phase interface-capturing
simulations. Used in conjunction with phaseSystem.
simulations.
SourceFiles
alphaContactAngleFvPatchScalarField.C

View File

@ -0,0 +1,159 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2022 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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "correctContactAngle.H"
#include "unitConversion.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
void Foam::correctContactAngle
(
const volScalarField& a1,
const volScalarField& a2,
const volVectorField::Boundary& Ubf,
const dimensionedScalar& deltaN,
surfaceVectorField::Boundary& nHatbf
)
{
const volScalarField::Boundary& a1bf = a1.boundaryField();
const volScalarField::Boundary& a2bf = a2.boundaryField();
const fvBoundaryMesh& boundary = a1.mesh().boundary();
forAll(boundary, patchi)
{
const fvPatchScalarField& a1p = a1bf[patchi];
const fvPatchScalarField& a2p = a2bf[patchi];
const bool a1pIsCa = isA<alphaContactAngleFvPatchScalarField>(a1p);
const bool a2pIsCa = isA<alphaContactAngleFvPatchScalarField>(a2p);
if (a1pIsCa || a2pIsCa)
{
if (a1pIsCa != a2pIsCa)
{
FatalErrorInFunction
<< alphaContactAngleFvPatchScalarField::typeName
<< " boundary condition specified on patch "
<< boundary[patchi].name() << " for "
<< (a1pIsCa ? a1.name() : a2.name()) << " but not for "
<< (a2pIsCa ? a1.name() : a2.name())
<< exit(FatalError);
}
const alphaContactAngleFvPatchScalarField& a1ca =
refCast<const alphaContactAngleFvPatchScalarField>(a1p);
const alphaContactAngleFvPatchScalarField& a2ca =
refCast<const alphaContactAngleFvPatchScalarField>(a2p);
const bool a1caHasProps = a1ca.thetaProps().found(a2.group());
const bool a2caHasProps = a2ca.thetaProps().found(a1.group());
if (!a1caHasProps && !a2caHasProps)
{
FatalErrorInFunction
<< "Neither "
<< alphaContactAngleFvPatchScalarField::typeName
<< " boundary condition specified on patch "
<< boundary[patchi].name()
<< " for " << a1.name() << " and " << a2.name()
<< " contains properties for the other phase"
<< exit(FatalError);
}
if
(
a1caHasProps && a2caHasProps
&& a1ca.thetaProps()[a2.group()]
!= a2ca.thetaProps()[a1.group()].reversed()
)
{
FatalErrorInFunction
<< "The "
<< alphaContactAngleFvPatchScalarField::typeName
<< " boundary conditions specified on patch "
<< boundary[patchi].name()
<< " for " << a1.name() << " and " << a2.name()
<< " contain inconsistent properties"
<< exit(FatalError);
}
const alphaContactAngleFvPatchScalarField::contactAngleProperties
tp = a1caHasProps
? a1ca.thetaProps()[a2.group()]
: a2ca.thetaProps()[a1.group()].reversed();
const vectorField np(a1.mesh().boundary()[patchi].nf());
vectorField& nHatp = nHatbf[patchi];
// Calculate the contact angle
scalarField theta(np.size(), degToRad(tp.theta0()));
// Calculate the dynamic contact angle if required
if (tp.dynamic())
{
const scalar uTheta = tp.uTheta();
const scalar thetaA = degToRad(tp.thetaA());
const scalar thetaR = degToRad(tp.thetaR());
// Calculated the component of the velocity parallel to the wall
vectorField Uwall
(
Ubf[patchi].patchInternalField() - Ubf[patchi]
);
Uwall -= (np & Uwall)*np;
// Find the direction of the interface parallel to the wall
vectorField nWall(nHatp - (np & nHatp)*np);
nWall /= (mag(nWall) + small);
// Calculate Uwall resolved normal to the interface parallel to
// the interface
const scalarField uwall(nWall & Uwall);
theta += (thetaA - thetaR)*tanh(uwall/uTheta);
}
// Reset nHatp to correspond to the contact angle
const scalarField a12(nHatp & np);
const scalarField b1(cos(theta));
scalarField b2(nHatp.size());
forAll(b2, facei)
{
b2[facei] = cos(acos(a12[facei]) - theta[facei]);
}
const scalarField det(1 - a12*a12);
const scalarField a((b1 - a12*b2)/det);
const scalarField b((b2 - a12*b1)/det);
nHatp = a*np + b*nHatp;
nHatp /= (mag(nHatp) + deltaN.value());
}
}
}
// ************************************************************************* //

View File

@ -0,0 +1,65 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2022 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 <http://www.gnu.org/licenses/>.
Class
Foam::correctContactAngle
Description
Correction for the boundary condition on the unit normal nHat on
walls to produce the correct contact angle. The dynamic contact angle is
calculated from the component of the velocity on the direction of the
interface, parallel to the wall.
SourceFiles
correctContactAngle.C
\*---------------------------------------------------------------------------*/
#ifndef correctContactAngle_H
#define correctContactAngle_H
#include "alphaContactAngleFvPatchScalarField.H"
#include "surfaceFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
//- Correct the contact angle for the two volume fraction fields
void correctContactAngle
(
const volScalarField& alpha1,
const volScalarField& alpha2,
const volVectorField::Boundary& Ubf,
const dimensionedScalar& deltaN,
surfaceVectorField::Boundary& nHatbf
);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -23,43 +23,34 @@ boundaryField
leftWall
{
type alphaContactAngle;
thetaProperties
(
( water air ) 90 0 0 0
( oil air ) 90 0 0 0
( mercury air ) 90 0 0 0
( water oil ) 90 0 0 0
( water mercury ) 90 0 0 0
( oil mercury ) 90 0 0 0
);
contactAngleProperties
{
oil { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
rightWall
{
type alphaContactAngle;
thetaProperties
(
( water air ) 90 0 0 0
( oil air ) 90 0 0 0
( mercury air ) 90 0 0 0
( water oil ) 90 0 0 0
( water mercury ) 90 0 0 0
( oil mercury ) 90 0 0 0
);
contactAngleProperties
{
oil { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 1;
}
lowerWall
{
type alphaContactAngle;
thetaProperties
(
( water air ) 90 0 0 0
( oil air ) 90 0 0 0
( mercury air ) 90 0 0 0
( water oil ) 90 0 0 0
( water mercury ) 90 0 0 0
( oil mercury ) 90 0 0 0
);
contactAngleProperties
{
oil { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
atmosphere

View File

@ -22,15 +22,36 @@ boundaryField
{
leftWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
water { theta0 90; }
}
value uniform 0;
}
rightWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
water { theta0 90; }
}
value uniform 0;
}
lowerWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
water { theta0 90; }
}
value uniform 0;
}
atmosphere
{

View File

@ -22,15 +22,36 @@ boundaryField
{
leftWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
rightWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
lowerWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
atmosphere
{

View File

@ -22,15 +22,36 @@ boundaryField
{
leftWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
rightWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
lowerWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
atmosphere
{

View File

@ -23,43 +23,34 @@ boundaryField
leftWall
{
type alphaContactAngle;
thetaProperties
(
( water air ) 90 0 0 0
( oil air ) 90 0 0 0
( mercury air ) 90 0 0 0
( water oil ) 90 0 0 0
( water mercury ) 90 0 0 0
( oil mercury ) 90 0 0 0
);
contactAngleProperties
{
oil { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
rightWall
{
type alphaContactAngle;
thetaProperties
(
( water air ) 90 0 0 0
( oil air ) 90 0 0 0
( mercury air ) 90 0 0 0
( water oil ) 90 0 0 0
( water mercury ) 90 0 0 0
( oil mercury ) 90 0 0 0
);
contactAngleProperties
{
oil { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 1;
}
lowerWall
{
type alphaContactAngle;
thetaProperties
(
( water air ) 90 0 0 0
( oil air ) 90 0 0 0
( mercury air ) 90 0 0 0
( water oil ) 90 0 0 0
( water mercury ) 90 0 0 0
( oil mercury ) 90 0 0 0
);
contactAngleProperties
{
oil { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
atmosphere

View File

@ -22,15 +22,36 @@ boundaryField
{
leftWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
water { theta0 90; }
}
value uniform 0;
}
rightWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
water { theta0 90; }
}
value uniform 0;
}
lowerWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
water { theta0 90; }
}
value uniform 0;
}
atmosphere
{

View File

@ -22,15 +22,36 @@ boundaryField
{
leftWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
rightWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
lowerWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
atmosphere
{

View File

@ -22,15 +22,36 @@ boundaryField
{
leftWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
rightWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
lowerWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
atmosphere
{

View File

@ -23,43 +23,34 @@ boundaryField
leftWall
{
type alphaContactAngle;
thetaProperties
(
( water air ) 90 0 0 0
( oil air ) 90 0 0 0
( mercury air ) 90 0 0 0
( water oil ) 90 0 0 0
( water mercury ) 90 0 0 0
( oil mercury ) 90 0 0 0
);
contactAngleProperties
{
oil { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
rightWall
{
type alphaContactAngle;
thetaProperties
(
( water air ) 90 0 0 0
( oil air ) 90 0 0 0
( mercury air ) 90 0 0 0
( water oil ) 90 0 0 0
( water mercury ) 90 0 0 0
( oil mercury ) 90 0 0 0
);
contactAngleProperties
{
oil { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 1;
}
lowerWall
{
type alphaContactAngle;
thetaProperties
(
( water air ) 90 0 0 0
( oil air ) 90 0 0 0
( mercury air ) 90 0 0 0
( water oil ) 90 0 0 0
( water mercury ) 90 0 0 0
( oil mercury ) 90 0 0 0
);
contactAngleProperties
{
oil { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
atmosphere

View File

@ -22,15 +22,36 @@ boundaryField
{
leftWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
water { theta0 90; }
}
value uniform 0;
}
rightWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
water { theta0 90; }
}
value uniform 0;
}
lowerWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
water { theta0 90; }
}
value uniform 0;
}
atmosphere
{

View File

@ -22,15 +22,36 @@ boundaryField
{
leftWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
rightWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
lowerWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
atmosphere
{

View File

@ -22,15 +22,36 @@ boundaryField
{
leftWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
rightWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
lowerWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
atmosphere
{

View File

@ -23,43 +23,34 @@ boundaryField
leftWall
{
type alphaContactAngle;
thetaProperties
(
( water air ) 90 0 0 0
( oil air ) 90 0 0 0
( mercury air ) 90 0 0 0
( water oil ) 90 0 0 0
( water mercury ) 90 0 0 0
( oil mercury ) 90 0 0 0
);
contactAngleProperties
{
oil { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
rightWall
{
type alphaContactAngle;
thetaProperties
(
( water air ) 90 0 0 0
( oil air ) 90 0 0 0
( mercury air ) 90 0 0 0
( water oil ) 90 0 0 0
( water mercury ) 90 0 0 0
( oil mercury ) 90 0 0 0
);
contactAngleProperties
{
oil { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 1;
}
lowerWall
{
type alphaContactAngle;
thetaProperties
(
( water air ) 90 0 0 0
( oil air ) 90 0 0 0
( mercury air ) 90 0 0 0
( water oil ) 90 0 0 0
( water mercury ) 90 0 0 0
( oil mercury ) 90 0 0 0
);
contactAngleProperties
{
oil { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
atmosphere

View File

@ -22,15 +22,36 @@ boundaryField
{
leftWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
water { theta0 90; }
}
value uniform 0;
}
rightWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
water { theta0 90; }
}
value uniform 0;
}
lowerWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
water { theta0 90; }
}
value uniform 0;
}
atmosphere
{

View File

@ -22,15 +22,36 @@ boundaryField
{
leftWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
rightWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
lowerWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
water { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
atmosphere
{

View File

@ -22,15 +22,36 @@ boundaryField
{
leftWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
rightWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
lowerWall
{
type zeroGradient;
type alphaContactAngle;
contactAngleProperties
{
air { theta0 90; }
oil { theta0 90; }
mercury { theta0 90; }
}
value uniform 0;
}
atmosphere
{