reactingEulerFoam: Added wall-boiling and phase change capability to populationBalance functionality

Introduced thermalPhaseChangePopulationBalanceTwo- and MultiphaseSystem as
user-selectable phaseSystems which are the first to actually use multiple mass
transfer mechanisms enabled by

commit d3a237f560.

The functionality is demonstrated using the reactingTwoPhaseEulerFoam
wallBoilingPolydisperse tutorial.

Patch contributed by VTT Technical Research Centre of Finland Ltd and Institute
of Fluid Dynamics, Helmholtz-Zentrum Dresden - Rossendorf (HZDR).
This commit is contained in:
Henry Weller
2018-01-24 14:57:14 +00:00
parent c902c7a396
commit 6e143e5ab0
99 changed files with 2254 additions and 2628 deletions

View File

@ -6,6 +6,7 @@ cd ${0%/*} || exit 1 # Run from this directory
wmakeLnInclude interfacialModels
wmakeLnInclude interfacialCompositionModels
wmakeLnInclude derivedFvPatchFields
wmake $targetType phaseSystems
wmake $targetType interfacialModels
wmake $targetType interfacialCompositionModels

View File

@ -34,6 +34,11 @@ populationBalanceModel/daughterSizeDistributionModels/uniformBinaryDsd/uniformBi
populationBalanceModel/driftModels/driftModel/driftModel.C
populationBalanceModel/driftModels/constantDrift/constantDrift.C
populationBalanceModel/driftModels/densityChange/densityChange.C
populationBalanceModel/driftModels/phaseChange/phaseChange.C
populationBalanceModel/nucleationModels/nucleationModel/nucleationModel.C
populationBalanceModel/nucleationModels/constantNucleation/constantNucleation.C
populationBalanceModel/nucleationModels/wallBoiling/wallBoiling.C
BlendedInterfacialModel/blendingMethods/blendingMethod/blendingMethod.C
BlendedInterfacialModel/blendingMethods/blendingMethod/newBlendingMethod.C

View File

@ -1,6 +1,7 @@
EXE_INC = \
-I../interfacialModels/lnInclude \
-I../interfacialCompositionModels/lnInclude \
-I../derivedFvPatchFields/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/reactionThermo/lnInclude \

View File

@ -359,8 +359,6 @@ void Foam::PopulationBalancePhaseSystem<BasePhaseSystem>::solve()
{
BasePhaseSystem::solve();
BasePhaseSystem::correct();
forAll(populationBalances_, i)
{
populationBalances_[i].solve();
@ -368,4 +366,4 @@ void Foam::PopulationBalancePhaseSystem<BasePhaseSystem>::solve()
}
// ************************************************************************* //1
// ************************************************************************* //

View File

@ -74,7 +74,7 @@ Foam::diameterModels::velocityGroup::secondMoment() const
const sizeGroup& fi = sizeGroups_[i];
m2 += sqr(fi.d())*formFactor()*fi
*max(fi.phase(), fi.phase().residualAlpha())/fi.x();
*max(fi.phase(), SMALL)/fi.x();
}
return tm2;
@ -106,7 +106,7 @@ Foam::diameterModels::velocityGroup::thirdMoment() const
const sizeGroup& fi = sizeGroups_[i];
m3 += pow3(fi.d())*formFactor()*fi
*max(fi.phase(), fi.phase().residualAlpha())/fi.x();
*max(fi.phase(), SMALL)/fi.x();
}
return tm3;
@ -308,6 +308,12 @@ Foam::diameterModels::velocityGroup::velocityGroup
{
if
(
phase_.mesh().solverDict(popBalName_).lookupOrDefault<Switch>
(
"renormalizeAtRestart",
false
)
||
phase_.mesh().solverDict(popBalName_).lookupOrDefault<Switch>
(
"renormalize",
@ -328,11 +334,18 @@ Foam::diameterModels::velocityGroup::velocityGroup
)
{
FatalErrorInFunction
<< "Initial values of the sizeGroups belonging to velocityGroup "
<< " Initial values of the sizeGroups belonging to velocityGroup "
<< this->phase().name()
<< " must add to unity. The sizeGroup fractions can be"
<< " renormalized by setting the renormalize switch"
<< " in the fvSolution subdictionary " << popBalName_ << "." << endl
<< " must add to" << nl << " unity. This condition might be"
<< " violated due to wrong entries in the" << nl
<< " velocityGroupCoeffs subdictionary or bad initial conditions in"
<< " the startTime" << nl
<< " directory. The sizeGroups can be renormalized at every"
<< " timestep or at restart" << nl
<< " only by setting the corresponding switch renormalize or"
<< " renormalizeAtRestart" << nl
<< " in the fvSolution subdictionary " << popBalName_ << "."
<< " Note that boundary conditions are not" << nl << "renormalized."
<< exit(FatalError);
}

View File

@ -79,13 +79,6 @@ Foam::diameterModels::binaryBreakupModel::binaryBreakupModel
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::diameterModels::populationBalanceModel&
Foam::diameterModels::binaryBreakupModel::popBal() const
{
return popBal_;
}
void Foam::diameterModels::binaryBreakupModel::correct()
{}

View File

@ -138,8 +138,11 @@ public:
// Member Functions
//- Return reference to populationBalance
const populationBalanceModel& popBal() const;
//- Return reference to the populationBalance
const populationBalanceModel& popBal() const
{
return popBal_;
}
//- Correct diameter independent expressions
virtual void correct();

View File

@ -82,13 +82,6 @@ Foam::diameterModels::breakupModel::breakupModel
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::diameterModels::populationBalanceModel&
Foam::diameterModels::breakupModel::popBal() const
{
return popBal_;
}
void Foam::diameterModels::breakupModel::correct()
{}

View File

@ -145,9 +145,12 @@ public:
// Member Functions
//- Return reference to the populationBalance
const populationBalanceModel& popBal() const;
const populationBalanceModel& popBal() const
{
return popBal_;
}
//- Return const reference to daughter size distribution pointer
//- Return const-reference to daughter size distribution pointer
const autoPtr<daughterSizeDistributionModel>& dsdPtr() const
{
return dsd_;

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -80,13 +80,6 @@ Foam::diameterModels::coalescenceModel::coalescenceModel
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::diameterModels::populationBalanceModel&
Foam::diameterModels::coalescenceModel::popBal() const
{
return popBal_;
}
void Foam::diameterModels::coalescenceModel::correct()
{}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -136,8 +136,11 @@ public:
// Member Functions
//- Return reference to populationBalance
const populationBalanceModel& popBal() const;
//- Return reference to the populationBalance
const populationBalanceModel& popBal() const
{
return popBal_;
}
//- Correct diameter independent expressions
virtual void correct();

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -79,13 +79,6 @@ Foam::diameterModels::driftModel::driftModel
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::diameterModels::populationBalanceModel&
Foam::diameterModels::driftModel::popBal() const
{
return popBal_;
}
void Foam::diameterModels::driftModel::correct()
{}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2017-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -133,8 +133,11 @@ public:
// Member Functions
//- Return reference to populationBalanceModel
const populationBalanceModel& popBal() const;
//- Return reference to the populationBalance
const populationBalanceModel& popBal() const
{
return popBal_;
}
//- Correct diameter independent expressions
virtual void correct();

View File

@ -0,0 +1,123 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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 "phaseChange.H"
#include "addToRunTimeSelectionTable.H"
#include "phaseSystem.H"
#include "phasePairKey.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace diameterModels
{
namespace driftModels
{
defineTypeNameAndDebug(phaseChange, 0);
addToRunTimeSelectionTable(driftModel, phaseChange, dictionary);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::diameterModels::driftModels::phaseChange::phaseChange
(
const populationBalanceModel& popBal,
const dictionary& dict
)
:
driftModel(popBal, dict),
pairNames_(dict.lookup("pairNames")),
iDmdt_
(
IOobject
(
"iDmdt",
popBal.time().timeName(),
popBal.mesh()
),
popBal.mesh(),
dimensionedScalar("Sui", dimDensity/dimTime, Zero)
),
N_
(
IOobject
(
"N",
popBal.mesh().time().timeName(),
popBal.mesh()
),
popBal.mesh(),
dimensionedScalar("Sui", inv(dimVolume), Zero)
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::diameterModels::driftModels::phaseChange::correct()
{
iDmdt_ *= 0.0;
forAll(pairNames_, i)
{
const word& pairName = pairNames_[i];
iDmdt_ +=
popBal_.mesh().lookupObject<volScalarField>
(
IOobject::groupName("iDmdt", pairName)
);
}
N_ *= 0.0;
forAll(popBal_.sizeGroups(), i)
{
const sizeGroup& fi = *popBal_.sizeGroups()[i];
N_ += fi*max(fi.phase(), SMALL)/fi.x();
}
}
void Foam::diameterModels::driftModels::phaseChange::driftRate
(
volScalarField& driftRate,
const label i
)
{
const sizeGroup& fi = *popBal_.sizeGroups()[i];
driftRate += iDmdt_/(N_*fi.phase().rho());
}
// ************************************************************************* //

View File

@ -0,0 +1,112 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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::diameterModels::driftModels::isothermal
Description
Drift induced by interfacial phaseChange.
SourceFiles
isothermal.C
\*---------------------------------------------------------------------------*/
#ifndef phaseChange_H
#define phaseChange_H
#include "driftModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace diameterModels
{
namespace driftModels
{
/*---------------------------------------------------------------------------*\
Class phaseChange Declaration
\*---------------------------------------------------------------------------*/
class phaseChange
:
public driftModel
{
// Private data
//- Names of unorderd phasePairs between which phaseChange occurs, i.e.
// "(gasIAndLiquid gasIIAndLiquid)"
List<word> pairNames_;
//- Total mass transfer rate due to phaseChange
volScalarField iDmdt_;
//- Total number concentration
volScalarField N_;
public:
//- Runtime type information
TypeName("phaseChange");
// Constructor
phaseChange
(
const populationBalanceModel& popBal,
const dictionary& dict
);
//- Destructor
virtual ~phaseChange()
{}
// Member Functions
//- Correct diameter independent expressions
virtual void correct();
//- Add to driftRate
virtual void driftRate
(
volScalarField& driftRate,
const label i
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace driftModels
} // End namespace diameterModels
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,117 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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 "constantNucleation.H"
#include "phaseSystem.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace diameterModels
{
namespace nucleationModels
{
defineTypeNameAndDebug(constantNucleation, 0);
addToRunTimeSelectionTable
(
nucleationModel,
constantNucleation,
dictionary
);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::diameterModels::nucleationModels::constantNucleation::
constantNucleation
(
const populationBalanceModel& popBal,
const dictionary& dict
)
:
nucleationModel(popBal, dict),
d_("departureDiameter", dimLength, dict),
velGroup_
(
refCast<const velocityGroup>
(
popBal.mesh().lookupObject<phaseModel>
(
IOobject::groupName
(
"alpha",
dict.lookup("velocityGroup")
)
).dPtr()()
)
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::diameterModels::nucleationModels::constantNucleation::correct()
{
if
(
d_.value() < velGroup_.sizeGroups().first().d().value()
|| d_.value() > velGroup_.sizeGroups().last().d().value()
)
{
WarningInFunction
<< "Departure diameter " << d_.value() << " m outside of range ["
<< velGroup_.sizeGroups().first().d().value() << ", "
<< velGroup_.sizeGroups().last().d().value() << "] m" << endl
<< " The nucleation rate is set to zero." << endl
<< " Adjust discretization over property space to suppress this"
<< " warning."
<< endl;
}
}
void Foam::diameterModels::nucleationModels::constantNucleation::
nucleationRate
(
volScalarField& nucleationRate,
const label i
)
{
const sizeGroup& fi = *popBal_.sizeGroups()[i];
phaseModel& phase = const_cast<phaseModel&>(fi.phase());
volScalarField& rho = phase.thermo().rho();
nucleationRate +=
popBal_.gamma(i, velGroup_.formFactor()*pow3(d_))
*(popBal_.fluid().fvOptions()(phase, rho)&rho)/rho/fi.x();
}
// ************************************************************************* //

View File

@ -0,0 +1,111 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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::diameterModels::nucleationModels::constant
Description
Constant nucleation rate within all classes. Used for verification and
validation of the nucleation formulation implemented in the
populationBalanceModel class. Rate is calculated from fvOptions mass source.
SourceFiles
constant.C
\*---------------------------------------------------------------------------*/
#ifndef constantNucleation_H
#define constantNucleation_H
#include "nucleationModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace diameterModels
{
namespace nucleationModels
{
/*---------------------------------------------------------------------------*\
Class constantNucleation Declaration
\*---------------------------------------------------------------------------*/
class constantNucleation
:
public nucleationModel
{
// Private data
//- Departure diameter
dimensionedScalar d_;
//- Velocity group in which the nucleation occurs
const velocityGroup& velGroup_;
public:
//- Runtime type information
TypeName("constant");
// Constructor
constantNucleation
(
const populationBalanceModel& popBal,
const dictionary& dict
);
//- Destructor
virtual ~constantNucleation()
{}
// Member Functions
//- Correct diameter independent expressions
virtual void correct();
//- Add to nucleationRate
virtual void nucleationRate
(
volScalarField& nucleationRate,
const label i
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace nucleationModels
} // End namespace diameterModels
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,86 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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 "nucleationModel.H"
#include "phaseSystem.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace diameterModels
{
defineTypeNameAndDebug(nucleationModel, 0);
defineRunTimeSelectionTable(nucleationModel, dictionary);
}
}
// * * * * * * * * * * * * * * * * Selector * * * * * * * * * * * * * * * * //
Foam::autoPtr<Foam::diameterModels::nucleationModel>
Foam::diameterModels::nucleationModel::New
(
const word& type,
const populationBalanceModel& popBal,
const dictionary& dict
)
{
dictionaryConstructorTable::iterator cstrIter =
dictionaryConstructorTablePtr_->find(type);
if (cstrIter == dictionaryConstructorTablePtr_->end())
{
FatalErrorInFunction
<< "Unknown zeroeth order model type "
<< type << nl << nl
<< "Valid zeroeth order model types : " << endl
<< dictionaryConstructorTablePtr_->sortedToc()
<< exit(FatalError);
}
return autoPtr<nucleationModel>(cstrIter()(popBal, dict));
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::diameterModels::nucleationModel::nucleationModel
(
const populationBalanceModel& popBal,
const dictionary& dict
)
:
popBal_(popBal)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::diameterModels::nucleationModel::correct()
{}
// ************************************************************************* //

View File

@ -0,0 +1,163 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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::diameterModels::nucleationModel
Description
Base class for nucleation models.
SourceFiles
nucleationModel.C
\*---------------------------------------------------------------------------*/
#ifndef nucleationModel_H
#define nucleationModel_H
#include "populationBalanceModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace diameterModels
{
/*---------------------------------------------------------------------------*\
Class nucleationModel Declaration
\*---------------------------------------------------------------------------*/
class nucleationModel
{
protected:
// Protected data
//- Reference to the populationBalanceModel
const populationBalanceModel& popBal_;
public:
//- Runtime type information
TypeName("nucleationModel");
// Declare run-time constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
nucleationModel,
dictionary,
(
const populationBalanceModel& popBal,
const dictionary& dict
),
(popBal, dict)
);
//- Class used for the read-construction of
// PtrLists of nucleation models
class iNew
{
const populationBalanceModel& popBal_;
public:
iNew(const populationBalanceModel& popBal)
:
popBal_(popBal)
{}
autoPtr<nucleationModel> operator()(Istream& is) const
{
word type(is);
dictionary dict(is);
return nucleationModel::New(type, popBal_, dict);
}
};
// Constructor
nucleationModel
(
const populationBalanceModel& popBal,
const dictionary& dict
);
autoPtr<nucleationModel> clone() const
{
NotImplemented;
return autoPtr<nucleationModel>(nullptr);
}
// Selector
static autoPtr<nucleationModel> New
(
const word& type,
const populationBalanceModel& popBal,
const dictionary& dict
);
//- Destructor
virtual ~nucleationModel()
{}
// Member Functions
//- Return reference to the populationBalance
const populationBalanceModel& popBal() const
{
return popBal_;
}
//- Correct diameter independent expressions
virtual void correct();
//- Add to nucleationRate
virtual void nucleationRate
(
volScalarField& nucleationRate,
const label i
) = 0;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace diameterModels
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,199 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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 "wallBoiling.H"
#include "alphatWallBoilingWallFunctionFvPatchScalarField.H"
#include "phaseSystem.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace diameterModels
{
namespace nucleationModels
{
defineTypeNameAndDebug(wallBoiling, 0);
addToRunTimeSelectionTable
(
nucleationModel,
wallBoiling,
dictionary
);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::diameterModels::nucleationModels::wallBoiling::
wallBoiling
(
const populationBalanceModel& popBal,
const dictionary& dict
)
:
nucleationModel(popBal, dict),
velGroup_
(
refCast<const velocityGroup>
(
popBal.mesh().lookupObject<phaseModel>
(
IOobject::groupName
(
"alpha",
dict.lookup("velocityGroup")
)
).dPtr()()
)
),
turbulence_
(
popBal_.mesh().lookupObjectRef<phaseCompressibleTurbulenceModel>
(
IOobject::groupName
(
turbulenceModel::propertiesName,
popBal_.continuousPhase().name()
)
)
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::diameterModels::nucleationModels::wallBoiling::correct()
{
const tmp<volScalarField> talphat(turbulence_.alphat());
const volScalarField::Boundary& alphatBf = talphat().boundaryField();
typedef compressible::alphatWallBoilingWallFunctionFvPatchScalarField
alphatWallBoilingWallFunction;
forAll(alphatBf, patchi)
{
if
(
isA<alphatWallBoilingWallFunction>(alphatBf[patchi])
)
{
const alphatWallBoilingWallFunction& alphatw =
refCast<const alphatWallBoilingWallFunction>(alphatBf[patchi]);
const scalarField& dDep = alphatw.dDeparture();
if (min(dDep) < velGroup_.sizeGroups().first().d().value())
{
Warning
<< "Minimum departure diameter " << min(dDep)
<< " m outside of range ["
<< velGroup_.sizeGroups().first().d().value() << ", "
<< velGroup_.sizeGroups().last().d().value() << "] m"
<< " at patch " << alphatw.patch().name()
<< endl
<< " The nucleation rate in populationBalance "
<< popBal_.name() << " is set to zero." << endl
<< " Adjust discretization over property space to"
<< " suppress this warning."
<< endl;
}
else if (max(dDep) > velGroup_.sizeGroups().last().d().value())
{
Warning
<< "Maximum departure diameter " << max(dDep)
<< " m outside of range ["
<< velGroup_.sizeGroups().first().d().value() << ", "
<< velGroup_.sizeGroups().last().d().value() << "] m"
<< " at patch " << alphatw.patch().name()
<< endl
<< " The nucleation rate in populationBalance "
<< popBal_.name() << " is set to zero." << endl
<< " Adjust discretization over property space to"
<< " suppress this warning."
<< endl;
}
}
}
}
void Foam::diameterModels::nucleationModels::wallBoiling::
nucleationRate
(
volScalarField& nucleationRate,
const label i
)
{
const sizeGroup& fi = *popBal_.sizeGroups()[i];
phaseModel& phase = const_cast<phaseModel&>(fi.phase());
volScalarField& rho = phase.thermo().rho();
const tmp<volScalarField> talphat(turbulence_.alphat());
const volScalarField::Boundary& alphatBf = talphat().boundaryField();
typedef compressible::alphatWallBoilingWallFunctionFvPatchScalarField
alphatWallBoilingWallFunction;
forAll(alphatBf, patchi)
{
if
(
isA<alphatWallBoilingWallFunction>(alphatBf[patchi])
)
{
const alphatWallBoilingWallFunction& alphatw =
refCast<const alphatWallBoilingWallFunction>(alphatBf[patchi]);
const scalarField& dmdt = alphatw.dmdt();
const scalarField& dDep = alphatw.dDeparture();
const labelList& faceCells = alphatw.patch().faceCells();
dimensionedScalar unitLength("unitLength", dimLength, 1.0);
forAll(alphatw, facei)
{
if (dmdt[facei] > SMALL)
{
const label faceCelli = faceCells[facei];
nucleationRate[faceCelli] +=
popBal_.gamma
(
i,
velGroup_.formFactor()*pow3(dDep[facei]*unitLength)
).value()
*dmdt[facei]/rho[faceCelli]/fi.x().value();
}
}
}
}
}
// ************************************************************************* //

View File

@ -0,0 +1,115 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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::diameterModels::nucleationModels::wall
Description
Wall-boiling model which requires a velocityGroup (i.e. phase) to be
specified in which the nucleation occurs. This setting must be consistent
with the specifications in the alphatWallBoilingWallFunction. If the
departure-diameter lies outside the diameter-range given by the sizeGroups
of the corresponding velocityGroup, the solver will give a warning and the
nucleation rate will be set to zero.
SourceFiles
wallBoiling.C
\*---------------------------------------------------------------------------*/
#ifndef wallBoiling_H
#define wallBoiling_H
#include "nucleationModel.H"
#include "phaseCompressibleTurbulenceModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace diameterModels
{
namespace nucleationModels
{
/*---------------------------------------------------------------------------*\
Class wallBoiling Declaration
\*---------------------------------------------------------------------------*/
class wallBoiling
:
public nucleationModel
{
// Private data
//- Velocity group in which the nucleation occurs
const velocityGroup& velGroup_;
//- Pointer to turbulence model
const phaseCompressibleTurbulenceModel& turbulence_;
public:
//- Runtime type information
TypeName("wallBoiling");
// Constructor
wallBoiling
(
const populationBalanceModel& popBal,
const dictionary& dict
);
//- Destructor
virtual ~wallBoiling()
{}
// Member Functions
//- Correct diameter independent expressions
virtual void correct();
//- Add to nucleationRate
virtual void nucleationRate
(
volScalarField& nucleationRate,
const label i
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace nucleationModels
} // End namespace diameterModels
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -28,6 +28,7 @@ License
#include "breakupModel.H"
#include "binaryBreakupModel.H"
#include "driftModel.H"
#include "nucleationModel.H"
#include "phaseSystem.H"
#include "fvmDdt.H"
#include "fvcDdt.H"
@ -36,7 +37,8 @@ License
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
void Foam::diameterModels::populationBalanceModel::registerVelocityGroups()
void
Foam::diameterModels::populationBalanceModel::registerVelocityAndSizeGroups()
{
forAll(fluid_.phases(), phasei)
{
@ -245,50 +247,10 @@ void Foam::diameterModels::populationBalanceModel::preSolve()
{
drift_[model].correct();
}
}
Foam::dimensionedScalar
Foam::diameterModels::populationBalanceModel::
gamma
(
const label i,
const dimensionedScalar& v
) const
{
dimensionedScalar lowerBoundary(v);
dimensionedScalar upperBoundary(v);
const dimensionedScalar& xi = sizeGroups_[i]->x();
if (i == 0)
forAll(nucleation_, model)
{
lowerBoundary = xi;
}
else
{
lowerBoundary = sizeGroups_[i-1]->x();
}
if (i == sizeGroups_.size() - 1)
{
upperBoundary = xi;
}
else
{
upperBoundary = sizeGroups_[i+1]->x();
}
if (v < lowerBoundary || v > upperBoundary)
{
return 0.0;
}
else if (v.value() <= xi.value())
{
return (v - lowerBoundary)/(xi - lowerBoundary);
}
else
{
return (upperBoundary - v)/(upperBoundary - xi);
nucleation_[model].correct();
}
}
@ -317,73 +279,54 @@ birthByCoalescence
const sizeGroup& fi = *sizeGroups_[i];
if (velocityGroups_.size() > 1)
// Avoid double counting of events
if (j == k)
{
// Avoid double counting of events
if (j == k)
{
Sui_() = 0.5*fi.x()*coalescenceRate_()*fj*alphaj/fj.x()*fk
*alphak/fk.x()*Gamma;
}
else
{
Sui_() = fi.x()*coalescenceRate_()*fj*alphaj/fj.x()*fk*alphak
/fk.x()*Gamma;
}
Su_[i] += Sui_();
dimensionedScalar ratio = fj.x()/fi.x();
const volScalarField& rho = fi.phase().rho();
const phasePairKey pairij
(
fi.phase().name(),
fj.phase().name()
);
// Check whether fi and fj reside in different velocityGroups
if (pDmdt_.found(pairij))
{
const scalar dmdtSign
(
Pair<word>::compare(pDmdt_.find(pairij).key(), pairij)
);
pDmdt_[pairij]->ref() += dmdtSign*ratio*Sui_()*rho;
}
const phasePairKey pairik
(
fi.phase().name(),
fk.phase().name()
);
// Check whether fi and fk reside in different velocityGroups
if (pDmdt_.found(pairik))
{
const scalar dmdtSign
(
Pair<word>::compare(pDmdt_.find(pairik).key(), pairik)
);
pDmdt_[pairik]->ref() += dmdtSign*(1 - ratio)*Sui_()*rho;
}
Sui_ = 0.5*fi.x()*coalescenceRate_()*fj*alphaj/fj.x()*fk*alphak
/fk.x()*Gamma;
}
else
{
// Avoid double counting of events
if (j == k)
{
Su_[i] += 0.5*fi.x()*coalescenceRate_()*fj*alphaj/fj.x()*fk
*alphak/fk.x()*Gamma;
}
else
{
Su_[i] += fi.x()*coalescenceRate_()*fj*alphaj/fj.x()*fk*alphak
/fk.x()*Gamma;
}
Sui_ = fi.x()*coalescenceRate_()*fj*alphaj/fj.x()*fk*alphak/fk.x()
*Gamma;
}
Su_[i] += Sui_;
dimensionedScalar ratio = fj.x()/fi.x();
const volScalarField& rho = fi.phase().rho();
const phasePairKey pairij
(
fi.phase().name(),
fj.phase().name()
);
if (pDmdt_.found(pairij))
{
const scalar dmdtSign
(
Pair<word>::compare(pDmdt_.find(pairij).key(), pairij)
);
pDmdt_[pairij]->ref() += dmdtSign*ratio*Sui_*rho;
}
const phasePairKey pairik
(
fi.phase().name(),
fk.phase().name()
);
if (pDmdt_.found(pairik))
{
const scalar dmdtSign
(
Pair<word>::compare(pDmdt_.find(pairik).key(), pairik)
);
pDmdt_[pairik]->ref() += dmdtSign*(1 - ratio)*Sui_*rho;
}
}
}
@ -429,36 +372,27 @@ birthByBreakup
{
const sizeGroup& fi = *sizeGroups_[i];
if (velocityGroups_.size() > 1)
Sui_ = fi.x()*breakupRate_()*breakup_[model].dsdPtr()().nik(i, k)*fk
*fk.phase()/fk.x();
Su_[i] += Sui_;
const volScalarField& rho = fi.phase().rho();
const phasePairKey pair
(
fi.phase().name(),
fk.phase().name()
);
if (pDmdt_.found(pair))
{
Sui_() = fi.x()*breakupRate_()*breakup_[model].dsdPtr()().nik(i, k)
*fk*fk.phase()/fk.x();
Su_[i] += Sui_();
const volScalarField& rho = fi.phase().rho();
const phasePairKey pair
const scalar dmdtSign
(
fi.phase().name(),
fk.phase().name()
Pair<word>::compare(pDmdt_.find(pair).key(), pair)
);
// Check whether fi and fk reside in different velocityGroups
if (pDmdt_.found(pair))
{
const scalar dmdtSign
(
Pair<word>::compare(pDmdt_.find(pair).key(), pair)
);
pDmdt_[pair]->ref() += dmdtSign*Sui_()*rho;
}
}
else
{
Su_[i] += fi.x()*breakupRate_()*breakup_[model].dsdPtr()().nik(i, k)
*fk*fk.phase()/fk.x();
pDmdt_[pair]->ref() += dmdtSign*Sui_*rho;
}
}
}
@ -521,32 +455,24 @@ birthByBinaryBreakup
const volScalarField& alphaj = fj.phase();
const volScalarField& rho = fj.phase().rho();
if (velocityGroups_.size() > 1)
Sui_ = fi.x()*binaryBreakupRate_()*delta_[i][j]*fj*alphaj/fj.x();
Su_[i] += Sui_;
const phasePairKey pairij
(
fi.phase().name(),
fj.phase().name()
);
if (pDmdt_.found(pairij))
{
Sui_() = fi.x()*binaryBreakupRate_()*delta_[i][j]*fj*alphaj/fj.x();
Su_[i] += Sui_();
const phasePairKey pairij
const scalar dmdtSign
(
fi.phase().name(),
fj.phase().name()
Pair<word>::compare(pDmdt_.find(pairij).key(), pairij)
);
// Check whether fi and fj reside in different velocityGroups
if (pDmdt_.found(pairij))
{
const scalar dmdtSign
(
Pair<word>::compare(pDmdt_.find(pairij).key(), pairij)
);
pDmdt_[pairij]->ref() += dmdtSign*Sui_()*rho;
}
}
else
{
Su_[i] += fi.x()*binaryBreakupRate_()*delta_[i][j]*fj*alphaj/fj.x();
pDmdt_[pairij]->ref() += dmdtSign*Sui_*rho;
}
dimensionedScalar Gamma;
@ -561,42 +487,32 @@ birthByBinaryBreakup
const sizeGroup& fk = *sizeGroups_[k];
if (velocityGroups_.size() > 1)
volScalarField& Suk = Sui_;
Suk = sizeGroups_[k]->x()*binaryBreakupRate_()*delta_[i][j]*fj*alphaj
/fj.x()*Gamma;
Su_[k] += Suk;
const phasePairKey pairkj
(
fk.phase().name(),
fj.phase().name()
);
if (pDmdt_.found(pairkj))
{
volScalarField& Suk = Sui_();
Suk = sizeGroups_[k]->x()*binaryBreakupRate_()*delta_[i][j]*fj
*alphaj/fj.x()*Gamma;
Su_[k] += Suk;
const phasePairKey pairkj
const scalar dmdtSign
(
fk.phase().name(),
fj.phase().name()
Pair<word>::compare
(
pDmdt_.find(pairkj).key(),
pairkj
)
);
// Check whether fk and fj reside in different velocityGroups
if (pDmdt_.found(pairkj))
{
const scalar dmdtSign
(
Pair<word>::compare
(
pDmdt_.find(pairkj).key(),
pairkj
)
);
pDmdt_[pairkj]->ref() += dmdtSign*Suk*rho;
}
pDmdt_[pairkj]->ref() += dmdtSign*Suk*rho;
}
else
{
Su_[k] += sizeGroups_[k]->x()*binaryBreakupRate_()*delta_[i][j]*fj
*alphaj/fj.x()*Gamma;
}
}
}
@ -616,117 +532,126 @@ deathByBinaryBreakup
void Foam::diameterModels::populationBalanceModel::drift(const label i)
{
r_() *= 0.0;
if (i == sizeGroups_.size() - 1)
{
r_() += pos(driftRate_())*sizeGroups_[i]->x()/sizeGroups_[i-1]->x();
}
else
{
r_() += pos(driftRate_())*sizeGroups_[i+1]->x()/sizeGroups_[i]->x();
}
if (i == 0)
{
r_() += neg(driftRate_())*sizeGroups_[i]->x()/sizeGroups_[i+1]->x();
}
else
{
r_() += neg(driftRate_())*sizeGroups_[i-1]->x()/sizeGroups_[i]->x();
}
const sizeGroup& fi = *sizeGroups_[i];
const volScalarField& rho = fi.phase().rho();
if (i == sizeGroups_.size() - 1)
if (i == 0)
{
SuSp_[i] += neg(driftRate_())*fi.x()*driftRate_()*fi.phase()/fi.x()
/((r_() - 1)*v_[i]);
rx_() = pos(driftRate_())*sizeGroups_[i+1]->x()/sizeGroups_[i]->x();
}
else if (i == 0)
else if (i == sizeGroups_.size() - 1)
{
SuSp_[i] += pos(driftRate_())*fi.x()*driftRate_()*fi.phase()/fi.x()
/((r_() - 1)*v_[i]);
rx_() = neg(driftRate_())*sizeGroups_[i-1]->x()/sizeGroups_[i]->x();
}
else
{
SuSp_[i] += fi.x()*driftRate_()*fi.phase()/fi.x()/((r_() - 1)*v_[i]);
rx_() = pos(driftRate_())*sizeGroups_[i+1]->x()/sizeGroups_[i]->x()
+ neg(driftRate_())*sizeGroups_[i-1]->x()/sizeGroups_[i]->x();
}
if (i != 0)
SuSp_[i] += (neg(1 - rx_()) + neg(1 - rx_()/(1 - rx_())))*driftRate_()
*fi.phase()/((rx_() - 1)*sizeGroups_[i]->x());
rx_() *= 0.0;
rdx_() *= 0.0;
if (i < sizeGroups_.size() - 2)
{
if (velocityGroups_.size() > 1)
{
const sizeGroup& fh = *sizeGroups_[i-1];
rx_() += pos(driftRate_())*sizeGroups_[i+2]->x()/sizeGroups_[i+1]->x();
volScalarField& Suh = Sui_();
rdx_() += pos(driftRate_())
*(sizeGroups_[i+2]->x() - sizeGroups_[i+1]->x())
/(sizeGroups_[i+1]->x() - sizeGroups_[i]->x());
}
else if (i == sizeGroups_.size() - 2)
{
rx_() += pos(driftRate_())*sizeGroups_[i+1]->x()
/sizeGroups_[i]->x();
Suh = neg(driftRate_())*fh.x()*r_()*driftRate_()*fi*fi.phase()
/fi.x()/((r_() - 1)*v_[i-1]);
rdx_() += pos(driftRate_())
*(sizeGroups_[i+1]->x() - sizeGroups_[i]->x())
/(sizeGroups_[i]->x() - sizeGroups_[i-1]->x());
}
const phasePairKey pair
(
fi.phase().name(),
fh.phase().name()
);
if (i == 1)
{
rx_() += neg(driftRate_())*sizeGroups_[i-1]->x()
/sizeGroups_[i]->x();
// Check whether fi and fh reside in different velocityGroups
if (pDmdt_.found(pair))
{
const scalar dmdtSign
(
Pair<word>::compare(pDmdt_.find(pair).key(), pair)
);
rdx_() += neg(driftRate_())
*(sizeGroups_[i]->x() - sizeGroups_[i-1]->x())
/(sizeGroups_[i+1]->x() - sizeGroups_[i]->x());
}
else if (i > 1)
{
rx_() += neg(driftRate_())*sizeGroups_[i-2]->x()/sizeGroups_[i-1]->x();
pDmdt_[pair]->ref() -= dmdtSign*Suh*rho;
}
Su_[i-1] += Suh;
}
else
{
Su_[i-1] += neg(driftRate_())*sizeGroups_[i-1]->x()*r_()
*driftRate_()*fi*fi.phase()/fi.x()/((r_() - 1)*v_[i-1]);
}
rdx_() += neg(driftRate_())
*(sizeGroups_[i-1]->x() - sizeGroups_[i-2]->x())
/(sizeGroups_[i]->x() - sizeGroups_[i-1]->x());
}
if (i != sizeGroups_.size() - 1)
{
if (velocityGroups_.size() > 1)
const sizeGroup& fj = *sizeGroups_[i+1];
volScalarField& Suj = Sui_;
Suj = pos(driftRate_())*driftRate_()*rdx_()*fi*fi.phase()/fi.x()
/(rx_() - 1);
Su_[i+1] += Suj;
const phasePairKey pairij
(
fi.phase().name(),
fj.phase().name()
);
if (pDmdt_.found(pairij))
{
const sizeGroup& fj = *sizeGroups_[i+1];
volScalarField& Suj = Sui_();
Suj = pos(driftRate_())*fj.x()*r_()*driftRate_()*fi*fi.phase()
/fi.x()/((r_() - 1)*v_[i+1]);
const phasePairKey pair
const scalar dmdtSign
(
fi.phase().name(),
fj.phase().name()
Pair<word>::compare(pDmdt_.find(pairij).key(), pairij)
);
// Check whether fi and fj reside in different velocityGroups
if (pDmdt_.found(pair))
{
const scalar dmdtSign
(
Pair<word>::compare(pDmdt_.find(pair).key(), pair)
);
pDmdt_[pair]->ref() -= dmdtSign*Suj*rho;
}
Su_[i+1] += Suj;
}
else
{
Su_[i+1] += pos(driftRate_())*sizeGroups_[i+1]->x()*r_()
*driftRate_()*fi*fi.phase()/fi.x()/((r_() - 1)*v_[i+1]);
pDmdt_[pairij]->ref() -= dmdtSign*Suj*rho;
}
}
if (i != 0)
{
const sizeGroup& fh = *sizeGroups_[i-1];
volScalarField& Suh = Sui_;
Suh = neg(driftRate_())*driftRate_()*rdx_()*fi*fi.phase()/fi.x()
/(rx_() - 1);
Su_[i-1] += Suh;
const phasePairKey pairih
(
fi.phase().name(),
fh.phase().name()
);
if (pDmdt_.found(pairih))
{
const scalar dmdtSign
(
Pair<word>::compare(pDmdt_.find(pairih).key(), pairih)
);
pDmdt_[pairih]->ref() -= dmdtSign*Suh*rho;
}
}
}
void Foam::diameterModels::populationBalanceModel::nucleation(const label i)
{
dimensionedScalar volume("volume", dimVolume, 1.0);
Su_[i] += sizeGroups_[i]->x()*nucleationRate_();
}
@ -830,6 +755,18 @@ void Foam::diameterModels::populationBalanceModel::sources()
drift(i);
}
if (nucleation_.size() != 0)
{
nucleationRate_() *= 0.0;
forAll(nucleation_, model)
{
nucleation_[model].nucleationRate(nucleationRate_(), i);
}
nucleation(i);
}
}
}
@ -872,7 +809,8 @@ void Foam::diameterModels::populationBalanceModel::calcVelocity()
forAllIter(PtrListDictionary<velocityGroup>, velocityGroups_, iter)
{
U_ += iter().phase().U()*iter().phase()
U_ += iter().phase().U()
*max(iter().phase(), iter().phase().residualAlpha())
/max(alphas_, iter().phase().residualAlpha());
}
}
@ -983,7 +921,17 @@ Foam::diameterModels::populationBalanceModel::populationBalanceModel
delta_(),
Su_(),
SuSp_(),
Sui_(),
Sui_
(
IOobject
(
"Sui",
fluid_.time().timeName(),
fluid_.mesh()
),
fluid_.mesh(),
dimensionedScalar("Sui", inv(dimTime), Zero)
),
coalescence_
(
dict_.lookup("coalescenceModels"),
@ -1008,7 +956,14 @@ Foam::diameterModels::populationBalanceModel::populationBalanceModel
driftModel::iNew(*this)
),
driftRate_(),
r_(),
rx_(),
rdx_(),
nucleation_
(
dict_.lookup("nucleationModels"),
nucleationModel::iNew(*this)
),
nucleationRate_(),
alphas_
(
IOobject
@ -1047,27 +1002,21 @@ Foam::diameterModels::populationBalanceModel::populationBalanceModel
),
d_()
{
this->registerVelocityGroups();
this->registerVelocityAndSizeGroups();
this->createPhasePairs();
if (sizeGroups_.size() < 3)
{
FatalErrorInFunction
<< "The populationBalance " << name_
<< " requires a minimum number of three sizeGroups to be"
<< " specified."
<< exit(FatalError);
}
if (velocityGroups_.size() > 1)
{
Sui_.reset
(
new volScalarField
(
IOobject
(
"Sui",
fluid_.time().timeName(),
fluid_.mesh()
),
fluid_.mesh(),
dimensionedScalar("Sui", inv(dimTime), Zero)
)
);
d_.reset
(
new volScalarField
@ -1169,7 +1118,7 @@ Foam::diameterModels::populationBalanceModel::populationBalanceModel
)
);
r_.reset
rx_.reset
(
new volScalarField
(
@ -1183,6 +1132,44 @@ Foam::diameterModels::populationBalanceModel::populationBalanceModel
dimensionedScalar("r", dimless, Zero)
)
);
rdx_.reset
(
new volScalarField
(
IOobject
(
"r",
fluid_.time().timeName(),
fluid_.mesh()
),
fluid_.mesh(),
dimensionedScalar("r", dimless, Zero)
)
);
}
if (nucleation_.size() != 0)
{
nucleationRate_.reset
(
new volScalarField
(
IOobject
(
"nucleationRate",
fluid.time().timeName(),
fluid.mesh()
),
fluid.mesh(),
dimensionedScalar
(
"nucleationRate",
inv(dimTime*dimVolume),
Zero
)
)
);
}
}
@ -1207,6 +1194,50 @@ bool Foam::diameterModels::populationBalanceModel::writeData(Ostream& os) const
}
const Foam::dimensionedScalar
Foam::diameterModels::populationBalanceModel::gamma
(
const label i,
const dimensionedScalar& v
) const
{
dimensionedScalar lowerBoundary(v);
dimensionedScalar upperBoundary(v);
const dimensionedScalar& xi = sizeGroups_[i]->x();
if (i == 0)
{
lowerBoundary = xi;
}
else
{
lowerBoundary = sizeGroups_[i-1]->x();
}
if (i == sizeGroups_.size() - 1)
{
upperBoundary = xi;
}
else
{
upperBoundary = sizeGroups_[i+1]->x();
}
if (v < lowerBoundary || v > upperBoundary)
{
return 0.0;
}
else if (v.value() <= xi.value())
{
return (v - lowerBoundary)/(xi - lowerBoundary);
}
else
{
return (upperBoundary - v)/(upperBoundary - xi);
}
}
void Foam::diameterModels::populationBalanceModel::solve()
{
const dictionary& solutionControls = mesh_.solverDict(name_);
@ -1312,6 +1343,17 @@ void Foam::diameterModels::populationBalanceModel::solve()
{
d_() = dsm();
}
volScalarField fAlpha0 =
*sizeGroups_.first()*sizeGroups_.first()->phase();
volScalarField fAlphaN =
*sizeGroups_.last()*sizeGroups_.last()->phase();
Info<< this->name() << " sizeGroup phase fraction first, last = "
<< fAlpha0.weightedAverage(this->mesh().V()).value()
<< ' ' << fAlphaN.weightedAverage(this->mesh().V()).value()
<< endl;
}
}

View File

@ -31,8 +31,8 @@ Description
a transport equation of the volume-based number density function. The
discretization is done using the fixed pivot technique of Kumar and
Ramkrishna (1996). The source terms are written in a way that particle
number and mass are preserved. Coalescence (aggregation), breakup as well
as drift (growth and surface loss) are supported.
number and mass are preserved. Coalescence (aggregation), breakup, drift
(growth and surface loss) as well as nucleation are supported.
For the discrete breakup term two recipies are available, depending on the
model choice. For models which state a total breakup rate and a separate
daughter size distribution function, the formulation of Kumar and Ramkrishna
@ -132,6 +132,9 @@ Usage
(
densityChange{}
);
nucleationModels
();
}
}
\endverbatim
@ -166,6 +169,7 @@ class coalescenceModel;
class breakupModel;
class binaryBreakupModel;
class driftModel;
class nucleationModel;
/*---------------------------------------------------------------------------*\
Class populationBalanceModel Declaration
@ -226,8 +230,8 @@ class populationBalanceModel
//- Sources treated implicitly or explicitly depending on sign
PtrList<volScalarField> SuSp_;
//- Field for caching pDmdt sources
autoPtr<volScalarField> Sui_;
//- Field for caching sources
volScalarField Sui_;
//- Coalescence models
PtrList<coalescenceModel> coalescence_;
@ -253,8 +257,17 @@ class populationBalanceModel
//- Drift rate
autoPtr<volScalarField> driftRate_;
//- Ratio between sucessive reprasentative volumes
autoPtr<volScalarField> r_;
//- Ratio between sucessive representative volumes
autoPtr<volScalarField> rx_;
//- Ratio between sucessive class widths
autoPtr<volScalarField> rdx_;
//- Zeroeth order models
PtrList<nucleationModel> nucleation_;
//- Zeroeth order rate
autoPtr<volScalarField> nucleationRate_;
//- Total void fraction of phases belonging to this populationBalance
volScalarField alphas_;
@ -268,7 +281,7 @@ class populationBalanceModel
// Private member functions
void registerVelocityGroups();
void registerVelocityAndSizeGroups();
void add(sizeGroup* group);
@ -276,12 +289,6 @@ class populationBalanceModel
void preSolve();
dimensionedScalar gamma
(
const label i,
const dimensionedScalar& v
) const;
void birthByCoalescence(const label j, const label k);
void deathByCoalescence(const label i, const label j);
@ -298,6 +305,8 @@ class populationBalanceModel
void drift(const label i);
void nucleation(const label i);
void sources();
void dmdt();
@ -401,6 +410,13 @@ public:
//- Return average velocity
inline const volVectorField& U() const;
//- Return allocation coefficient
const dimensionedScalar gamma
(
const label i,
const dimensionedScalar& v
) const;
//- Solve the population balance equation
void solve();
};

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2017 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2015-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -123,9 +123,26 @@ namespace Foam
populationBalanceMultiphaseSystem
);
typedef
ThermalPhaseChangePhaseSystem
<
PopulationBalancePhaseSystem
<
HeatAndMassTransferPhaseSystem
<
MomentumTransferPhaseSystem<multiphaseSystem>
>
>
>
thermalPhaseChangePopulationBalanceMultiphaseSystem;
addNamedToRunTimeSelectionTable
(
multiphaseSystem,
thermalPhaseChangePopulationBalanceMultiphaseSystem,
dictionary,
thermalPhaseChangePopulationBalanceMultiphaseSystem
);
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2017 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2015-2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -121,6 +121,27 @@ namespace Foam
dictionary,
populationBalanceTwoPhaseSystem
);
typedef
ThermalPhaseChangePhaseSystem
<
PopulationBalancePhaseSystem
<
HeatAndMassTransferPhaseSystem
<
MomentumTransferPhaseSystem<twoPhaseSystem>
>
>
>
thermalPhaseChangePopulationBalanceTwoPhaseSystem;
addNamedToRunTimeSelectionTable
(
twoPhaseSystem,
thermalPhaseChangePopulationBalanceTwoPhaseSystem,
dictionary,
thermalPhaseChangePopulationBalanceTwoPhaseSystem
);
}