mirror of
https://github.com/ParticulateFlow/CFDEMcoupling-PFM.git
synced 2025-12-08 06:37:44 +00:00
Merge pull request #120 from ParticulateFlow/feature/recurrence_chemistry
Feature/recurrence chemistry
This commit is contained in:
@ -1,8 +1,11 @@
|
|||||||
|
particleCloud.otherForces(fOther);
|
||||||
|
|
||||||
fvVectorMatrix UEqn
|
fvVectorMatrix UEqn
|
||||||
(
|
(
|
||||||
fvm::ddt(voidfraction,U) - fvm::Sp(fvc::ddt(voidfraction),U)
|
fvm::ddt(voidfraction,U) - fvm::Sp(fvc::ddt(voidfraction),U)
|
||||||
+ fvm::div(phi,U) - fvm::Sp(fvc::div(phi),U)
|
+ fvm::div(phi,U) - fvm::Sp(fvc::div(phi),U)
|
||||||
+ particleCloud.divVoidfractionTau(U, voidfraction)
|
+ particleCloud.divVoidfractionTau(U, voidfraction)
|
||||||
|
- fOther/rho
|
||||||
==
|
==
|
||||||
fvOptions(U)
|
fvOptions(U)
|
||||||
- fvm::Sp(Ksl/rho,U)
|
- fvm::Sp(Ksl/rho,U)
|
||||||
|
|||||||
@ -46,6 +46,21 @@
|
|||||||
//dimensionedScalar("0", dimensionSet(1, -3, -1, 0, 0), 1.0)
|
//dimensionedScalar("0", dimensionSet(1, -3, -1, 0, 0), 1.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Info<< "\nCreating body force field\n" << endl;
|
||||||
|
volVectorField fOther
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"fOther",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedVector("zero", dimensionSet(1,-2,-2,0,0,0,0), vector::zero)
|
||||||
|
);
|
||||||
|
|
||||||
Info<< "\nReading voidfraction field voidfraction = (Vgas/Vparticle)\n" << endl;
|
Info<< "\nReading voidfraction field voidfraction = (Vgas/Vparticle)\n" << endl;
|
||||||
volScalarField voidfraction
|
volScalarField voidfraction
|
||||||
(
|
(
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
cfdemSolverPisoFreeStreaming.C
|
||||||
|
|
||||||
|
EXE=$(CFDEM_APP_DIR)/cfdemSolverPisoFreeStreaming
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
include $(CFDEM_ADD_LIBS_DIR)/additionalLibs
|
||||||
|
|
||||||
|
EXE_INC = \
|
||||||
|
-I$(CFDEM_OFVERSION_DIR) \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
|
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
|
||||||
|
-I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \
|
||||||
|
-I$(LIB_SRC)/transportModels \
|
||||||
|
-I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
|
||||||
|
-I$(FOAM_SOLVERS)/incompressible/pisoFoam \
|
||||||
|
-I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/lnInclude \
|
||||||
|
-I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/cfdTools \
|
||||||
|
-I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/derived/cfdemCloudRec \
|
||||||
|
-I$(LIB_SRC)/sampling/lnInclude
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-L$(CFDEM_LIB_DIR)\
|
||||||
|
-lturbulenceModels \
|
||||||
|
-lincompressibleTurbulenceModels \
|
||||||
|
-lincompressibleTransportModels \
|
||||||
|
-lfiniteVolume \
|
||||||
|
-lmeshTools \
|
||||||
|
-lfvOptions \
|
||||||
|
-lsampling \
|
||||||
|
-l$(CFDEM_LIB_NAME) \
|
||||||
|
$(CFDEM_ADD_LIB_PATHS) \
|
||||||
|
$(CFDEM_ADD_LIBS)
|
||||||
@ -0,0 +1,126 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
CFDEMcoupling - Open Source CFD-DEM coupling
|
||||||
|
|
||||||
|
CFDEMcoupling is part of the CFDEMproject
|
||||||
|
www.cfdem.com
|
||||||
|
Christoph Goniva, christoph.goniva@cfdem.com
|
||||||
|
Copyright (C) 1991-2009 OpenCFD Ltd.
|
||||||
|
Copyright (C) 2009-2012 JKU, Linz
|
||||||
|
Copyright (C) 2012- DCS Computing GmbH,Linz
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of CFDEMcoupling.
|
||||||
|
|
||||||
|
CFDEMcoupling 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.
|
||||||
|
|
||||||
|
CFDEMcoupling 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 CFDEMcoupling. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Application
|
||||||
|
cfdemSolverPisoFreeStreaming
|
||||||
|
|
||||||
|
Description
|
||||||
|
Transient solver for incompressible flow.
|
||||||
|
Turbulence modelling is generic, i.e. laminar, RAS or LES may be selected.
|
||||||
|
The code is an evolution of the solver pisoFoam in OpenFOAM(R) 1.6,
|
||||||
|
where additional functionality for CFD-DEM coupling is added.
|
||||||
|
the particles follow the fluid velocity
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "fvCFD.H"
|
||||||
|
#include "singlePhaseTransportModel.H"
|
||||||
|
#include "turbulentTransportModel.H"
|
||||||
|
#include "pisoControl.H"
|
||||||
|
#include "fvOptions.H"
|
||||||
|
|
||||||
|
#include "cfdemCloudRec.H"
|
||||||
|
|
||||||
|
#include "cfdemCloud.H"
|
||||||
|
#include "implicitCouple.H"
|
||||||
|
#include "clockModel.H"
|
||||||
|
#include "smoothingModel.H"
|
||||||
|
#include "forceModel.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
#include "postProcess.H"
|
||||||
|
#include "setRootCase.H"
|
||||||
|
#include "createTime.H"
|
||||||
|
#include "createMesh.H"
|
||||||
|
#include "createControl.H"
|
||||||
|
#include "createFields.H"
|
||||||
|
#include "createFvOptions.H"
|
||||||
|
#include "initContinuityErrs.H"
|
||||||
|
|
||||||
|
cfdemCloudRec<cfdemCloud> particleCloud(mesh);
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
Info<< "\nStarting time loop\n" << endl;
|
||||||
|
while (runTime.loop())
|
||||||
|
{
|
||||||
|
|
||||||
|
particleCloud.clockM().start(1,"Global");
|
||||||
|
|
||||||
|
Info<< "Time = " << runTime.timeName() << nl << endl;
|
||||||
|
|
||||||
|
#include "CourantNo.H"
|
||||||
|
|
||||||
|
// do particle stuff
|
||||||
|
particleCloud.clockM().start(2,"Coupling");
|
||||||
|
|
||||||
|
particleCloud.evolve(voidfraction,Us,U);
|
||||||
|
|
||||||
|
|
||||||
|
particleCloud.clockM().stop("Coupling");
|
||||||
|
|
||||||
|
particleCloud.clockM().start(26,"Flow");
|
||||||
|
|
||||||
|
if(particleCloud.solveFlow())
|
||||||
|
{
|
||||||
|
// Pressure-velocity PISO corrector
|
||||||
|
{
|
||||||
|
// Momentum predictor
|
||||||
|
#include "UEqn.H"
|
||||||
|
|
||||||
|
// --- PISO loop
|
||||||
|
|
||||||
|
while (piso.correct())
|
||||||
|
{
|
||||||
|
#include "pEqn.H"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
laminarTransport.correct();
|
||||||
|
turbulence->correct();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Info << "skipping flow solution." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
runTime.write();
|
||||||
|
|
||||||
|
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
|
||||||
|
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
|
||||||
|
<< nl << endl;
|
||||||
|
|
||||||
|
particleCloud.clockM().stop("Flow");
|
||||||
|
particleCloud.clockM().stop("Global");
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< "End\n" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
110
applications/solvers/cfdemSolverPisoFreeStreaming/createFields.H
Normal file
110
applications/solvers/cfdemSolverPisoFreeStreaming/createFields.H
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
Info<< "Reading field p\n" << endl;
|
||||||
|
volScalarField p
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"p",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "Reading physical velocity field U" << endl;
|
||||||
|
Info<< "Note: only if voidfraction at boundary is 1, U is superficial velocity!!!\n" << endl;
|
||||||
|
volVectorField U
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"U",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
//===============================
|
||||||
|
// particle interaction modelling
|
||||||
|
//===============================
|
||||||
|
|
||||||
|
Info<< "\nReading voidfraction field voidfraction = (Vgas/Vparticle)\n" << endl;
|
||||||
|
volScalarField voidfraction
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"voidfraction",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "\nCreating density field rho\n" << endl;
|
||||||
|
volScalarField rho
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"rho",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "Reading particle velocity field Us\n" << endl;
|
||||||
|
volVectorField Us
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"Us",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
//===============================
|
||||||
|
|
||||||
|
//# include "createPhi.H"
|
||||||
|
#ifndef createPhi_H
|
||||||
|
#define createPhi_H
|
||||||
|
Info<< "Reading/calculating face flux field phi\n" << endl;
|
||||||
|
surfaceScalarField phi
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"phi",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
linearInterpolate(U) & mesh.Sf()
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
label pRefCell = 0;
|
||||||
|
scalar pRefValue = 0.0;
|
||||||
|
setRefCell(p, mesh.solutionDict().subDict("PISO"), pRefCell, pRefValue);
|
||||||
|
|
||||||
|
|
||||||
|
singlePhaseTransportModel laminarTransport(U, phi);
|
||||||
|
|
||||||
|
autoPtr<incompressible::turbulenceModel> turbulence
|
||||||
|
(
|
||||||
|
incompressible::turbulenceModel::New(U, phi, laminarTransport)
|
||||||
|
);
|
||||||
|
|
||||||
|
#include "createMRF.H"
|
||||||
@ -46,6 +46,21 @@
|
|||||||
//dimensionedScalar("0", dimensionSet(0, 0, -1, 0, 0), 1.0)
|
//dimensionedScalar("0", dimensionSet(0, 0, -1, 0, 0), 1.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Info<< "\nCreating body force field\n" << endl;
|
||||||
|
volVectorField fOther
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"fOther",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedVector("zero", dimensionSet(1,-2,-2,0,0,0,0), vector::zero)
|
||||||
|
);
|
||||||
|
|
||||||
Info<< "\nReading voidfraction field voidfraction = (Vgas/Vparticle)\n" << endl;
|
Info<< "\nReading voidfraction field voidfraction = (Vgas/Vparticle)\n" << endl;
|
||||||
volScalarField voidfraction
|
volScalarField voidfraction
|
||||||
(
|
(
|
||||||
|
|||||||
@ -20,21 +20,23 @@
|
|||||||
|
|
||||||
Cpv = he.name() == "e" ? thermo.Cv() : thermo.Cp();
|
Cpv = he.name() == "e" ? thermo.Cv() : thermo.Cp();
|
||||||
|
|
||||||
// correct source for the thermodynamic reference temperature
|
// For implict T terms in the energy/enthalpy transport equation, use
|
||||||
dimensionedScalar Tref("Tref", dimTemperature, T[0]-he[0]/(Cpv[0]+SMALL));
|
// (he_n+1 - he_n) / (T_n+1 - T_n) = Cpv to eliminate T_n+1 with he_n+1.
|
||||||
Qsource += QCoeff*Tref;
|
// This formula is valid for ideal gases with e=e(T) and h=h(T). For
|
||||||
|
// incompressible fluids, e=e(T) holds, too, but enthalpy would need correction
|
||||||
|
// terms accounting for pressure variations.
|
||||||
|
|
||||||
fvScalarMatrix EEqn
|
fvScalarMatrix EEqn
|
||||||
(
|
(
|
||||||
fvm::ddt(rhoeps, he) + fvm::div(phi, he)
|
fvm::ddt(rhoeps, he) + fvm::div(phi, he)
|
||||||
+ addSource
|
+ addSource
|
||||||
// net heat transfer from particles to fluid
|
|
||||||
- Qsource
|
- Qsource
|
||||||
|
- QCoeff*T
|
||||||
- fvm::Sp(QCoeff/Cpv, he)
|
- fvm::Sp(QCoeff/Cpv, he)
|
||||||
// thermal conduction of the fluid with effective conductivity
|
+ QCoeff/Cpv*he
|
||||||
|
- fvc::laplacian(voidfraction*thCond,T)
|
||||||
- fvm::laplacian(voidfraction*thCond/Cpv,he)
|
- fvm::laplacian(voidfraction*thCond/Cpv,he)
|
||||||
// + particle-fluid energy transfer due to work
|
+ fvc::laplacian(voidfraction*thCond/Cpv,he)
|
||||||
// + fluid energy dissipation due to shearing
|
|
||||||
==
|
==
|
||||||
fvOptions(rho, he)
|
fvOptions(rho, he)
|
||||||
);
|
);
|
||||||
|
|||||||
@ -37,12 +37,20 @@
|
|||||||
"URec",
|
"URec",
|
||||||
runTime.timeName(),
|
runTime.timeName(),
|
||||||
mesh,
|
mesh,
|
||||||
IOobject::MUST_READ,
|
IOobject::READ_IF_PRESENT,
|
||||||
IOobject::AUTO_WRITE
|
IOobject::NO_WRITE
|
||||||
),
|
),
|
||||||
mesh
|
mesh,
|
||||||
|
dimensionedVector("URec", dimensionSet(0, 1, -1, 0, 0), vector::zero)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
bool updateURec = false;
|
||||||
|
if (URec.headerOk())
|
||||||
|
{
|
||||||
|
updateURec = true;
|
||||||
|
URec.writeOpt() = IOobject::AUTO_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
volScalarField voidfractionRec
|
volScalarField voidfractionRec
|
||||||
(
|
(
|
||||||
IOobject
|
IOobject
|
||||||
@ -50,12 +58,20 @@
|
|||||||
"voidfractionRec",
|
"voidfractionRec",
|
||||||
runTime.timeName(),
|
runTime.timeName(),
|
||||||
mesh,
|
mesh,
|
||||||
IOobject::MUST_READ,
|
IOobject::READ_IF_PRESENT,
|
||||||
IOobject::AUTO_WRITE
|
IOobject::NO_WRITE
|
||||||
),
|
),
|
||||||
mesh
|
mesh,
|
||||||
|
dimensionedScalar("voidfractionRec", dimensionSet(0, 0, 0, 0, 0), 1.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
bool updateVoidfractionRec = false;
|
||||||
|
if (voidfractionRec.headerOk())
|
||||||
|
{
|
||||||
|
updateVoidfractionRec = true;
|
||||||
|
voidfractionRec.writeOpt() = IOobject::AUTO_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
volVectorField UsRec
|
volVectorField UsRec
|
||||||
(
|
(
|
||||||
IOobject
|
IOobject
|
||||||
@ -63,12 +79,20 @@
|
|||||||
"UsRec",
|
"UsRec",
|
||||||
runTime.timeName(),
|
runTime.timeName(),
|
||||||
mesh,
|
mesh,
|
||||||
IOobject::MUST_READ,
|
IOobject::READ_IF_PRESENT,
|
||||||
IOobject::AUTO_WRITE
|
IOobject::AUTO_WRITE
|
||||||
),
|
),
|
||||||
mesh
|
mesh,
|
||||||
|
dimensionedVector("URec", dimensionSet(0, 1, -1, 0, 0), vector::zero)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
bool updateUsRec = false;
|
||||||
|
if (UsRec.headerOk())
|
||||||
|
{
|
||||||
|
updateUsRec = true;
|
||||||
|
UsRec.writeOpt() = IOobject::AUTO_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
// calculated fields
|
// calculated fields
|
||||||
Info << "\nCreating fields subject to calculation\n" << endl;
|
Info << "\nCreating fields subject to calculation\n" << endl;
|
||||||
volScalarField voidfraction
|
volScalarField voidfraction
|
||||||
@ -78,7 +102,7 @@
|
|||||||
"voidfraction",
|
"voidfraction",
|
||||||
runTime.timeName(),
|
runTime.timeName(),
|
||||||
mesh,
|
mesh,
|
||||||
IOobject::NO_READ,
|
IOobject::READ_IF_PRESENT,
|
||||||
IOobject::AUTO_WRITE
|
IOobject::AUTO_WRITE
|
||||||
),
|
),
|
||||||
voidfractionRec
|
voidfractionRec
|
||||||
@ -91,7 +115,7 @@
|
|||||||
"Us",
|
"Us",
|
||||||
runTime.timeName(),
|
runTime.timeName(),
|
||||||
mesh,
|
mesh,
|
||||||
IOobject::NO_READ,
|
IOobject::READ_IF_PRESENT,
|
||||||
IOobject::AUTO_WRITE
|
IOobject::AUTO_WRITE
|
||||||
),
|
),
|
||||||
UsRec
|
UsRec
|
||||||
@ -111,11 +135,18 @@
|
|||||||
runTime.timeName(),
|
runTime.timeName(),
|
||||||
mesh,
|
mesh,
|
||||||
IOobject::READ_IF_PRESENT,
|
IOobject::READ_IF_PRESENT,
|
||||||
IOobject::AUTO_WRITE
|
IOobject::NO_WRITE
|
||||||
),
|
),
|
||||||
linearInterpolate(URec*voidfractionRec) & mesh.Sf()
|
linearInterpolate(URec*voidfractionRec) & mesh.Sf()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
bool updatePhiRec = false;
|
||||||
|
if (phiRec.headerOk())
|
||||||
|
{
|
||||||
|
updatePhiRec = true;
|
||||||
|
phiRec.writeOpt() = IOobject::AUTO_WRITE;
|
||||||
phiRec.write();
|
phiRec.write();
|
||||||
|
}
|
||||||
|
|
||||||
singlePhaseTransportModel laminarTransport(URec, phiRec);
|
singlePhaseTransportModel laminarTransport(URec, phiRec);
|
||||||
|
|
||||||
@ -123,3 +154,40 @@
|
|||||||
(
|
(
|
||||||
incompressible::turbulenceModel::New(URec, phiRec, laminarTransport)
|
incompressible::turbulenceModel::New(URec, phiRec, laminarTransport)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
IOdictionary recDict
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"recProperties",
|
||||||
|
runTime.constant(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
word voidfractionFieldName(recDict.lookupOrDefault<word>("voidfractionFieldName","voidfraction"));
|
||||||
|
word UFieldName(recDict.lookupOrDefault<word>("UFieldName","U"));
|
||||||
|
word UsFieldName(recDict.lookupOrDefault<word>("UsFieldName","Us"));
|
||||||
|
word fluxFieldName(recDict.lookupOrDefault<word>("fluxFieldName","phi"));
|
||||||
|
|
||||||
|
|
||||||
|
// place to put weight functions
|
||||||
|
IOdictionary weightDict
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"weightDict",
|
||||||
|
runTime.constant(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (!weightDict.headerOk())
|
||||||
|
{
|
||||||
|
weightDict.add("weights",scalarList(1,1.0));
|
||||||
|
}
|
||||||
|
scalarList weights(weightDict.lookup("weights"));
|
||||||
|
Info << "database initial weights: " << weights << endl;
|
||||||
|
|||||||
@ -43,6 +43,7 @@ Rules
|
|||||||
#include "cfdemCloudRec.H"
|
#include "cfdemCloudRec.H"
|
||||||
#include "recBase.H"
|
#include "recBase.H"
|
||||||
#include "recModel.H"
|
#include "recModel.H"
|
||||||
|
#include "recPath.H"
|
||||||
|
|
||||||
#include "cfdemCloud.H"
|
#include "cfdemCloud.H"
|
||||||
#include "clockModel.H"
|
#include "clockModel.H"
|
||||||
@ -59,6 +60,8 @@ int main(int argc, char *argv[])
|
|||||||
#include "createFields.H"
|
#include "createFields.H"
|
||||||
#include "createFvOptions.H"
|
#include "createFvOptions.H"
|
||||||
|
|
||||||
|
#include "readGravitationalAcceleration.H"
|
||||||
|
|
||||||
cfdemCloudRec<cfdemCloud> particleCloud(mesh);
|
cfdemCloudRec<cfdemCloud> particleCloud(mesh);
|
||||||
recBase recurrenceBase(mesh);
|
recBase recurrenceBase(mesh);
|
||||||
|
|
||||||
@ -88,8 +91,9 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if ( runTime.timeOutputValue() - startTime - (recTimeIndex+1)*recTimeStep + 1.0e-5 > 0.0 )
|
if ( runTime.timeOutputValue() - startTime - (recTimeIndex+1)*recTimeStep + 1.0e-5 > 0.0 )
|
||||||
{
|
{
|
||||||
|
Info << "updating recurrence fields at time " << runTime.timeName() << "with recTimeIndex = " << recTimeIndex << nl << endl;
|
||||||
recurrenceBase.updateRecFields();
|
recurrenceBase.updateRecFields();
|
||||||
#include "readFields.H"
|
#include "updateFields.H"
|
||||||
recTimeIndex++;
|
recTimeIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
29
applications/solvers/rcfdemSolverBase/updateFields.H
Normal file
29
applications/solvers/rcfdemSolverBase/updateFields.H
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
scalarList wList(weightDict.lookupOrDefault("weights",scalarList(1,1.0)));
|
||||||
|
|
||||||
|
recurrenceBase.recP().updateIntervalWeights(wList);
|
||||||
|
|
||||||
|
if(recurrenceBase.recM().endOfPath())
|
||||||
|
{
|
||||||
|
recurrenceBase.extendPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update fields where necessary
|
||||||
|
if (updateVoidfractionRec)
|
||||||
|
{
|
||||||
|
recurrenceBase.recM().exportVolScalarField(voidfractionFieldName,voidfractionRec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateURec)
|
||||||
|
{
|
||||||
|
recurrenceBase.recM().exportVolVectorField(UFieldName,URec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateUsRec)
|
||||||
|
{
|
||||||
|
recurrenceBase.recM().exportVolVectorField(UsFieldName,UsRec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatePhiRec)
|
||||||
|
{
|
||||||
|
recurrenceBase.recM().exportSurfaceScalarField(fluxFieldName,phiRec);
|
||||||
|
}
|
||||||
@ -10,6 +10,7 @@
|
|||||||
// main contribution due to gas expansion, not due to transport of kinetic energy
|
// main contribution due to gas expansion, not due to transport of kinetic energy
|
||||||
// fvc::ddt(rhoeps, K) + fvc::div(phiRec, K)
|
// fvc::ddt(rhoeps, K) + fvc::div(phiRec, K)
|
||||||
|
|
||||||
|
// assuming constant Cv such that e = Cv * T
|
||||||
fvScalarMatrix TEqn =
|
fvScalarMatrix TEqn =
|
||||||
(
|
(
|
||||||
fvm::ddt(rhoeps, T)
|
fvm::ddt(rhoeps, T)
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
rcfdemSolverForcedTracers.C
|
||||||
|
|
||||||
|
EXE=$(CFDEM_APP_DIR)/rcfdemSolverForcedTracers
|
||||||
27
applications/solvers/rcfdemSolverForcedTracers/Make/options
Normal file
27
applications/solvers/rcfdemSolverForcedTracers/Make/options
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
include $(CFDEM_ADD_LIBS_DIR)/additionalLibs
|
||||||
|
|
||||||
|
EXE_INC = \
|
||||||
|
-I$(CFDEM_OFVERSION_DIR) \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
|
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
|
||||||
|
-I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \
|
||||||
|
-I$(LIB_SRC)/transportModels \
|
||||||
|
-I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
|
||||||
|
-I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/lnInclude \
|
||||||
|
-I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/cfdTools \
|
||||||
|
-I$(CFDEM_SRC_DIR)/recurrence/lnInclude \
|
||||||
|
-I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/derived/cfdemCloudRec \
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-L$(CFDEM_LIB_DIR)\
|
||||||
|
-lrecurrence \
|
||||||
|
-lturbulenceModels \
|
||||||
|
-lincompressibleTurbulenceModels \
|
||||||
|
-lincompressibleTransportModels \
|
||||||
|
-lfiniteVolume \
|
||||||
|
-lmeshTools \
|
||||||
|
-lfvOptions \
|
||||||
|
-l$(CFDEM_LIB_NAME) \
|
||||||
|
$(CFDEM_ADD_LIB_PATHS) \
|
||||||
|
$(CFDEM_ADD_LIBS)
|
||||||
113
applications/solvers/rcfdemSolverForcedTracers/createFields.H
Normal file
113
applications/solvers/rcfdemSolverForcedTracers/createFields.H
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// dummy fields
|
||||||
|
Info << "\nCreating dummy density field\n" << endl;
|
||||||
|
|
||||||
|
volScalarField rho
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"rho",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("rho", dimensionSet(1, -3, 0, 0, 0), 1.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
// particle fields
|
||||||
|
Info << "\nCreating voidfraction and particle velocity fields\n" << endl;
|
||||||
|
|
||||||
|
volScalarField voidfraction
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"voidfraction",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
volVectorField Us
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"Us",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
// recurrence fields
|
||||||
|
Info << "\nCreating recurrence fields.\n" << endl;
|
||||||
|
|
||||||
|
volScalarField pRec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"pRec",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("p", dimensionSet(1, 2, -2, 0, 0), 1.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
volScalarField kRec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"kRec",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("k", dimensionSet(0, 2, -2, 0, 0), 0.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
volVectorField URec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"URec",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
//===============================
|
||||||
|
|
||||||
|
Info << "Calculating face flux field phi\n" << endl;
|
||||||
|
surfaceScalarField phiRec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"phiRec",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
linearInterpolate(URec*voidfraction) & mesh.Sf()
|
||||||
|
);
|
||||||
|
phiRec.write();
|
||||||
|
|
||||||
|
singlePhaseTransportModel laminarTransport(URec, phiRec);
|
||||||
|
|
||||||
|
autoPtr<incompressible::turbulenceModel> turbulence
|
||||||
|
(
|
||||||
|
incompressible::turbulenceModel::New(URec, phiRec, laminarTransport)
|
||||||
|
);
|
||||||
@ -0,0 +1,112 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
CFDEMcoupling academic - Open Source CFD-DEM coupling
|
||||||
|
|
||||||
|
Contributing authors:
|
||||||
|
Thomas Lichtenegger
|
||||||
|
Copyright (C) 2015- Johannes Kepler University, Linz
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of CFDEMcoupling academic.
|
||||||
|
|
||||||
|
CFDEMcoupling academic 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.
|
||||||
|
|
||||||
|
CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Application
|
||||||
|
rcfdemSolverForcedTracers
|
||||||
|
|
||||||
|
Description
|
||||||
|
Moves tracers according to the activated force models on pressure and velocity
|
||||||
|
fields provided by a recurrence process
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "fvCFD.H"
|
||||||
|
#include "singlePhaseTransportModel.H"
|
||||||
|
#include "turbulentTransportModel.H"
|
||||||
|
#include "fvOptions.H"
|
||||||
|
|
||||||
|
#include "recBase.H"
|
||||||
|
#include "recModel.H"
|
||||||
|
|
||||||
|
#include "cfdemCloud.H"
|
||||||
|
#include "clockModel.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
#include "postProcess.H"
|
||||||
|
#include "setRootCase.H"
|
||||||
|
#include "createTime.H"
|
||||||
|
#include "createMesh.H"
|
||||||
|
#include "createControl.H"
|
||||||
|
#include "createFields.H"
|
||||||
|
#include "createFvOptions.H"
|
||||||
|
|
||||||
|
cfdemCloud particleCloud(mesh);
|
||||||
|
recBase recurrenceBase(mesh);
|
||||||
|
|
||||||
|
const IOdictionary& recProps = mesh.lookupObject<IOdictionary>("recProperties");
|
||||||
|
bool useRecP(recProps.lookupOrDefault<bool>("useRecP",false));
|
||||||
|
bool useRecK(recProps.lookupOrDefault<bool>("useRecK",false));
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Info << "\nCalculating particle trajectories based on recurrence statistics\n" << endl;
|
||||||
|
|
||||||
|
label recTimeIndex = 0;
|
||||||
|
scalar recTimeStep = recurrenceBase.recM().recTimeStep();
|
||||||
|
scalar startTime = runTime.startTime().value();
|
||||||
|
|
||||||
|
while (runTime.run())
|
||||||
|
{
|
||||||
|
runTime++;
|
||||||
|
|
||||||
|
// do stuff (every lagrangian time step)
|
||||||
|
particleCloud.clockM().start(1,"Global");
|
||||||
|
|
||||||
|
Info << "Time = " << runTime.timeName() << nl << endl;
|
||||||
|
|
||||||
|
particleCloud.clockM().start(2,"Coupling");
|
||||||
|
|
||||||
|
particleCloud.evolve(voidfraction,Us,URec);
|
||||||
|
|
||||||
|
particleCloud.clockM().stop("Coupling");
|
||||||
|
|
||||||
|
|
||||||
|
if ( runTime.timeOutputValue() - startTime - (recTimeIndex+1)*recTimeStep + 1.0e-5 > 0.0 )
|
||||||
|
{
|
||||||
|
recurrenceBase.updateRecFields();
|
||||||
|
#include "updateFields.H"
|
||||||
|
recTimeIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
particleCloud.clockM().start(27,"Output");
|
||||||
|
runTime.write();
|
||||||
|
particleCloud.clockM().stop("Output");
|
||||||
|
|
||||||
|
particleCloud.clockM().stop("Global");
|
||||||
|
|
||||||
|
Info << "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
|
||||||
|
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
|
||||||
|
<< nl << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Info << "End\n" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
recurrenceBase.recM().exportVolVectorField("U",URec);
|
||||||
|
|
||||||
|
if (useRecP)
|
||||||
|
{
|
||||||
|
recurrenceBase.recM().exportVolScalarField("p",pRec);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useRecK)
|
||||||
|
{
|
||||||
|
recurrenceBase.recM().exportVolScalarField("k",kRec);
|
||||||
|
// in case database contains the velocity variance instead of k, do
|
||||||
|
// kRec *= 0.5;
|
||||||
|
}
|
||||||
@ -22,19 +22,33 @@
|
|||||||
|
|
||||||
Cpv = he.name() == "e" ? thermo.Cv() : thermo.Cp();
|
Cpv = he.name() == "e" ? thermo.Cv() : thermo.Cp();
|
||||||
|
|
||||||
|
// For implict T terms in the energy/enthalpy transport equation, use
|
||||||
|
// (he_n+1 - he_n) / (T_n+1 - T_n) = Cpv to eliminate T_n+1 with he_n+1.
|
||||||
|
// This formula is valid for ideal gases with e=e(T) and h=h(T). For
|
||||||
|
// incompressible fluids, e=e(T) holds, too, but enthalpy would need correction
|
||||||
|
// terms accounting for pressure variations.
|
||||||
|
|
||||||
fvScalarMatrix EEqn
|
fvScalarMatrix EEqn
|
||||||
(
|
(
|
||||||
fvm::div(phi, he)
|
fvm::div(phi, he)
|
||||||
+ addSource
|
+ addSource
|
||||||
- Qsource
|
- Qsource
|
||||||
|
- QCoeff*T
|
||||||
- fvm::Sp(QCoeff/Cpv, he)
|
- fvm::Sp(QCoeff/Cpv, he)
|
||||||
// - fvm::laplacian(voidfractionRec*kf/Cpv,he)
|
+ QCoeff/Cpv*he
|
||||||
|
- fvc::laplacian(voidfractionRec*thCond,T)
|
||||||
- fvm::laplacian(voidfractionRec*thCond/Cpv,he)
|
- fvm::laplacian(voidfractionRec*thCond/Cpv,he)
|
||||||
|
+ fvc::laplacian(voidfractionRec*thCond/Cpv,he)
|
||||||
==
|
==
|
||||||
fvOptions(rho, he)
|
fvOptions(rho, he)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (transientEEqn)
|
||||||
|
{
|
||||||
|
EEqn += fvm::ddt(rho,voidfractionRec,he);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
EEqn.relax();
|
EEqn.relax();
|
||||||
|
|
||||||
fvOptions.constrain(EEqn);
|
fvOptions.constrain(EEqn);
|
||||||
|
|||||||
@ -168,6 +168,8 @@ Info<< "Reading thermophysical properties\n" << endl;
|
|||||||
linearInterpolate(rho*U*voidfraction) & mesh.Sf()
|
linearInterpolate(rho*U*voidfraction) & mesh.Sf()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
bool transientEEqn(pimple.dict().lookupOrDefault<bool>("transientEEqn",false));
|
||||||
|
|
||||||
dimensionedScalar rhoMax
|
dimensionedScalar rhoMax
|
||||||
(
|
(
|
||||||
dimensionedScalar::lookupOrDefault
|
dimensionedScalar::lookupOrDefault
|
||||||
|
|||||||
67
applications/solvers/rcfdemSolverRhoSteadyPimpleChem/EEqn.H
Normal file
67
applications/solvers/rcfdemSolverRhoSteadyPimpleChem/EEqn.H
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
// contributions to internal energy equation can be found in
|
||||||
|
// Crowe et al.: "Multiphase flows with droplets and particles", CRC Press 1998
|
||||||
|
{
|
||||||
|
// dim he = J / kg
|
||||||
|
volScalarField& he = thermo.he();
|
||||||
|
particleCloud.energyContributions(Qsource);
|
||||||
|
particleCloud.energyCoefficients(QCoeff);
|
||||||
|
|
||||||
|
addSource =
|
||||||
|
(
|
||||||
|
he.name() == "e"
|
||||||
|
?
|
||||||
|
fvc::div(phi, K) +
|
||||||
|
fvc::div
|
||||||
|
(
|
||||||
|
fvc::absolute(phi/fvc::interpolate(rho), voidfractionRec*U),
|
||||||
|
p,
|
||||||
|
"div(phiv,p)"
|
||||||
|
)
|
||||||
|
: fvc::div(phi, K)
|
||||||
|
);
|
||||||
|
|
||||||
|
Cpv = he.name() == "e" ? thermo.Cv() : thermo.Cp();
|
||||||
|
|
||||||
|
// For implict T terms in the energy/enthalpy transport equation, use
|
||||||
|
// (he_n+1 - he_n) / (T_n+1 - T_n) = Cpv to eliminate T_n+1 with he_n+1.
|
||||||
|
// This formula is valid for ideal gases with e=e(T) and h=h(T). For
|
||||||
|
// incompressible fluids, e=e(T) holds, too, but enthalpy would need correction
|
||||||
|
// terms accounting for pressure variations.
|
||||||
|
|
||||||
|
fvScalarMatrix EEqn
|
||||||
|
(
|
||||||
|
fvm::div(phi, he)
|
||||||
|
+ addSource
|
||||||
|
- Qsource
|
||||||
|
- QCoeff*T
|
||||||
|
- fvm::Sp(QCoeff/Cpv, he)
|
||||||
|
+ QCoeff/Cpv*he
|
||||||
|
- fvc::laplacian(voidfractionRec*thCond,T)
|
||||||
|
- fvm::laplacian(voidfractionRec*thCond/Cpv,he)
|
||||||
|
+ fvc::laplacian(voidfractionRec*thCond/Cpv,he)
|
||||||
|
==
|
||||||
|
fvOptions(rho, he)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (transientEEqn)
|
||||||
|
{
|
||||||
|
EEqn += fvm::ddt(rho,voidfractionRec,he);
|
||||||
|
}
|
||||||
|
|
||||||
|
EEqn.relax();
|
||||||
|
|
||||||
|
fvOptions.constrain(EEqn);
|
||||||
|
|
||||||
|
EEqn.solve();
|
||||||
|
|
||||||
|
fvOptions.correct(he);
|
||||||
|
|
||||||
|
thermo.correct();
|
||||||
|
|
||||||
|
Info<< "T max/min : " << max(T).value() << " " << min(T).value() << endl;
|
||||||
|
|
||||||
|
|
||||||
|
particleCloud.clockM().start(31,"energySolve");
|
||||||
|
particleCloud.solve();
|
||||||
|
particleCloud.clockM().stop("energySolve");
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
rcfdemSolverRhoSteadyPimpleChem.C
|
||||||
|
|
||||||
|
EXE=$(CFDEM_APP_DIR)/rcfdemSolverRhoSteadyPimpleChem
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
include $(CFDEM_ADD_LIBS_DIR)/additionalLibs
|
||||||
|
|
||||||
|
FOAM_VERSION_MAJOR := $(word 1,$(subst ., ,$(WM_PROJECT_VERSION)))
|
||||||
|
PFLAGS+= -DOPENFOAM_VERSION_MAJOR=$(FOAM_VERSION_MAJOR)
|
||||||
|
PFLAGS+= -Dcompre
|
||||||
|
|
||||||
|
EXE_INC = \
|
||||||
|
$(PFLAGS) \
|
||||||
|
-I$(CFDEM_OFVERSION_DIR) \
|
||||||
|
-I$(LIB_SRC)/transportModels/compressible/lnInclude \
|
||||||
|
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
|
||||||
|
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
|
||||||
|
-I$(LIB_SRC)/TurbulenceModels/compressible/lnInclude \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/cfdTools \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
|
-I$(LIB_SRC)/sampling/lnInclude \
|
||||||
|
-I$(LIB_SRC)/fvOptions/lnInclude \
|
||||||
|
-I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/lnInclude \
|
||||||
|
-I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/cfdTools \
|
||||||
|
-I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \
|
||||||
|
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
|
||||||
|
-I$(LIB_SRC)/thermophysicalModels/reactionThermo/lnInclude \
|
||||||
|
-I$(LIB_SRC)/thermophysicalModels/chemistryModel/lnInclude \
|
||||||
|
-I$(LIB_SRC)/regionModels/regionModel/lnInclude \
|
||||||
|
-I$(LIB_SRC)/regionModels/surfaceFilmModels/lnInclude \
|
||||||
|
-I$(LIB_SRC)/ODE/lnInclude \
|
||||||
|
-I$(LIB_SRC)/combustionModels/lnInclude \
|
||||||
|
-I$(CFDEM_SRC_DIR)/recurrence/lnInclude \
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-L$(CFDEM_LIB_DIR)\
|
||||||
|
-lrecurrence \
|
||||||
|
-lcompressibleTransportModels \
|
||||||
|
-lfluidThermophysicalModels \
|
||||||
|
-lspecie \
|
||||||
|
-lturbulenceModels \
|
||||||
|
-lcompressibleTurbulenceModels \
|
||||||
|
-lfiniteVolume \
|
||||||
|
-lmeshTools \
|
||||||
|
-lsampling \
|
||||||
|
-lfvOptions \
|
||||||
|
-l$(CFDEM_LIB_COMP_NAME) \
|
||||||
|
$(CFDEM_ADD_LIB_PATHS) \
|
||||||
|
$(CFDEM_ADD_LIBS) \
|
||||||
|
-lreactionThermophysicalModels \
|
||||||
|
-lchemistryModel \
|
||||||
|
-lradiationModels \
|
||||||
|
-lregionModels \
|
||||||
|
-lsurfaceFilmModels \
|
||||||
|
-lODE \
|
||||||
|
-lcombustionModels
|
||||||
35
applications/solvers/rcfdemSolverRhoSteadyPimpleChem/UEqn.H
Normal file
35
applications/solvers/rcfdemSolverRhoSteadyPimpleChem/UEqn.H
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// Solve the Momentum equation
|
||||||
|
particleCloud.otherForces(fOther);
|
||||||
|
|
||||||
|
fvVectorMatrix UEqn
|
||||||
|
(
|
||||||
|
fvm::div(phi, U)
|
||||||
|
+ particleCloud.divVoidfractionTau(U, voidfractionRec)
|
||||||
|
+ fvm::Sp(Ksl,U)
|
||||||
|
- fOther
|
||||||
|
==
|
||||||
|
fvOptions(rho, U)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (stepcounter%nEveryFlow==0)
|
||||||
|
{
|
||||||
|
UEqn.relax();
|
||||||
|
|
||||||
|
fvOptions.constrain(UEqn);
|
||||||
|
|
||||||
|
if (modelType=="B" || modelType=="Bfull")
|
||||||
|
{
|
||||||
|
solve(UEqn == -fvc::grad(p)+ Ksl*UsRec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
solve(UEqn == -voidfractionRec*fvc::grad(p)+ Ksl*UsRec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#include "limitU.H"
|
||||||
|
|
||||||
|
fvOptions.correct(U);
|
||||||
|
|
||||||
|
K = 0.5*magSqr(U);
|
||||||
|
}
|
||||||
81
applications/solvers/rcfdemSolverRhoSteadyPimpleChem/YEqn.H
Normal file
81
applications/solvers/rcfdemSolverRhoSteadyPimpleChem/YEqn.H
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
particleCloud.clockM().start(29,"Y");
|
||||||
|
|
||||||
|
tmp<fv::convectionScheme<scalar> > mvConvection
|
||||||
|
(
|
||||||
|
fv::convectionScheme<scalar>::New
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
fields,
|
||||||
|
phi,
|
||||||
|
mesh.divScheme("div(phi,Yi_h)")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
{
|
||||||
|
combustion->correct();
|
||||||
|
#if OPENFOAM_VERSION_MAJOR < 5
|
||||||
|
dQ = combustion->dQ();
|
||||||
|
#else
|
||||||
|
Qdot = combustion->Qdot();
|
||||||
|
#endif
|
||||||
|
label inertIndex = -1;
|
||||||
|
volScalarField Yt(0.0*Y[0]);
|
||||||
|
|
||||||
|
forAll(Y, i)
|
||||||
|
{
|
||||||
|
if (Y[i].name() == inertSpecie) inertIndex = i;
|
||||||
|
if (Y[i].name() != inertSpecie || propagateInertSpecie)
|
||||||
|
{
|
||||||
|
volScalarField& Yi = Y[i];
|
||||||
|
|
||||||
|
fvScalarMatrix YiEqn
|
||||||
|
(
|
||||||
|
mvConvection->fvmDiv(phi, Yi)
|
||||||
|
- fvm::laplacian(voidfractionRec*turbulence->muEff(), Yi)
|
||||||
|
==
|
||||||
|
combustion->R(Yi)
|
||||||
|
+ particleCloud.chemistryM(0).Smi(i)*p/p.prevIter()
|
||||||
|
+ fvOptions(rho, Yi)
|
||||||
|
);
|
||||||
|
|
||||||
|
YiEqn.relax();
|
||||||
|
|
||||||
|
fvOptions.constrain(YiEqn);
|
||||||
|
|
||||||
|
YiEqn.solve(mesh.solver("Yi"));
|
||||||
|
|
||||||
|
Yi.relax();
|
||||||
|
|
||||||
|
fvOptions.correct(Yi);
|
||||||
|
|
||||||
|
Yi.max(0.0);
|
||||||
|
if (Y[i].name() != inertSpecie) Yt += Yi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inertIndex!=-1)
|
||||||
|
{
|
||||||
|
Y[inertIndex].max(inertLowerBound);
|
||||||
|
Y[inertIndex].min(inertUpperBound);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propagateInertSpecie)
|
||||||
|
{
|
||||||
|
if (inertIndex!=-1) Yt /= (1-Y[inertIndex] + ROOTVSMALL);
|
||||||
|
forAll(Y,i)
|
||||||
|
{
|
||||||
|
if (i!=inertIndex)
|
||||||
|
{
|
||||||
|
volScalarField& Yi = Y[i];
|
||||||
|
Yi = Yi/(Yt+ROOTVSMALL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Y[inertIndex] = scalar(1) - Yt;
|
||||||
|
Y[inertIndex].max(0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
particleCloud.clockM().stop("Y");
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
const volScalarField& T = thermo.T();
|
||||||
|
const volScalarField& psi = thermo.psi();
|
||||||
@ -0,0 +1,404 @@
|
|||||||
|
Info<< "Reading thermophysical properties\n" << endl;
|
||||||
|
|
||||||
|
#if OPENFOAM_VERSION_MAJOR < 6
|
||||||
|
Info<< "Creating combustion model\n" << endl;
|
||||||
|
autoPtr<combustionModels::rhoCombustionModel> combustion
|
||||||
|
(
|
||||||
|
combustionModels::rhoCombustionModel::New(mesh)
|
||||||
|
);
|
||||||
|
rhoReactionThermo& thermo = combustion->thermo();
|
||||||
|
#else
|
||||||
|
Info<< "Reading thermophysical properties\n" << endl;
|
||||||
|
autoPtr<rhoReactionThermo> pThermo(rhoReactionThermo::New(mesh));
|
||||||
|
rhoReactionThermo& thermo = pThermo();
|
||||||
|
#endif
|
||||||
|
thermo.validate(args.executable(), "h", "e");
|
||||||
|
|
||||||
|
basicSpecieMixture& composition = thermo.composition();
|
||||||
|
PtrList<volScalarField>& Y = composition.Y();
|
||||||
|
|
||||||
|
// read molecular weight
|
||||||
|
#if OPENFOAM_VERSION_MAJOR < 6
|
||||||
|
volScalarField W(composition.W());
|
||||||
|
#else
|
||||||
|
volScalarField W(thermo.W());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool propagateInertSpecie(thermo.lookupOrDefault<bool>("propagateInertSpecie",true));
|
||||||
|
|
||||||
|
const word inertSpecie(thermo.lookupOrDefault<word>("inertSpecie","none"));
|
||||||
|
|
||||||
|
const scalar inertLowerBound(thermo.lookupOrDefault<scalar>("inertLowerBound",0.0));
|
||||||
|
|
||||||
|
const scalar inertUpperBound(thermo.lookupOrDefault<scalar>("inertUpperBound",1.0));
|
||||||
|
|
||||||
|
if (!composition.contains(inertSpecie) && inertSpecie != "none")
|
||||||
|
{
|
||||||
|
FatalErrorIn(args.executable())
|
||||||
|
<< "Specified inert specie '" << inertSpecie << "' not found in "
|
||||||
|
<< "species list. Available species:" << composition.species()
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
volScalarField& p = thermo.p();
|
||||||
|
const volScalarField& T = thermo.T();
|
||||||
|
const volScalarField& psi = thermo.psi();
|
||||||
|
|
||||||
|
multivariateSurfaceInterpolationScheme<scalar>::fieldTable fields;
|
||||||
|
|
||||||
|
forAll(Y, i)
|
||||||
|
{
|
||||||
|
fields.add(Y[i]);
|
||||||
|
}
|
||||||
|
fields.add(thermo.he());
|
||||||
|
|
||||||
|
Info<< "Reading field rho\n" << endl;
|
||||||
|
volScalarField rho
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"rho",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
thermo.rho()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
Info<< "Reading field U\n" << endl;
|
||||||
|
volVectorField U
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"U",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "\nReading voidfraction field voidfraction = (Vgas/Vparticle)\n" << endl;
|
||||||
|
volScalarField voidfraction
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"voidfraction",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
volScalarField voidfractionRec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"voidfractionRec",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
voidfraction
|
||||||
|
);
|
||||||
|
|
||||||
|
volScalarField addSource
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"addSource",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "\nCreating fluid-particle heat flux field\n" << endl;
|
||||||
|
volScalarField Qsource
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"Qsource",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "\nCreating fluid-particle heat flux coefficient field\n" << endl;
|
||||||
|
volScalarField QCoeff
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"QCoeff",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("zero", dimensionSet(1,-1,-3,-1,0,0,0), 0.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "\nCreating thermal conductivity field\n" << endl;
|
||||||
|
volScalarField thCond
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"thCond",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("zero", dimensionSet(1,1,-3,-1,0,0,0), 0.0),
|
||||||
|
"zeroGradient"
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "\nCreating heat capacity field\n" << endl;
|
||||||
|
volScalarField Cpv
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"Cpv",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("zero", dimensionSet(0,2,-2,-1,0,0,0), 0.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "\nCreating body force field\n" << endl;
|
||||||
|
volVectorField fOther
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"fOther",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedVector("zero", dimensionSet(1,-2,-2,0,0,0,0), vector::zero)
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "Reading/calculating face flux field phi\n" << endl;
|
||||||
|
surfaceScalarField phi
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"phi",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
linearInterpolate(rho*U*voidfraction) & mesh.Sf()
|
||||||
|
);
|
||||||
|
|
||||||
|
bool transientEEqn(pimple.dict().lookupOrDefault<bool>("transientEEqn",false));
|
||||||
|
|
||||||
|
dimensionedScalar rhoMax
|
||||||
|
(
|
||||||
|
dimensionedScalar::lookupOrDefault
|
||||||
|
(
|
||||||
|
"rhoMax",
|
||||||
|
pimple.dict(),
|
||||||
|
dimDensity,
|
||||||
|
GREAT
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
dimensionedScalar rhoMin
|
||||||
|
(
|
||||||
|
dimensionedScalar::lookupOrDefault
|
||||||
|
(
|
||||||
|
"rhoMin",
|
||||||
|
pimple.dict(),
|
||||||
|
dimDensity,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
dimensionedScalar pMax
|
||||||
|
(
|
||||||
|
dimensionedScalar::lookupOrDefault
|
||||||
|
(
|
||||||
|
"pMax",
|
||||||
|
pimple.dict(),
|
||||||
|
dimPressure,
|
||||||
|
GREAT
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
dimensionedScalar pMin
|
||||||
|
(
|
||||||
|
dimensionedScalar::lookupOrDefault
|
||||||
|
(
|
||||||
|
"pMin",
|
||||||
|
pimple.dict(),
|
||||||
|
dimPressure,
|
||||||
|
-GREAT
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
dimensionedScalar UMax
|
||||||
|
(
|
||||||
|
dimensionedScalar::lookupOrDefault
|
||||||
|
(
|
||||||
|
"UMax",
|
||||||
|
pimple.dict(),
|
||||||
|
dimVelocity,
|
||||||
|
-1.0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "Creating turbulence model\n" << endl;
|
||||||
|
autoPtr<compressible::turbulenceModel> turbulence
|
||||||
|
(
|
||||||
|
compressible::turbulenceModel::New
|
||||||
|
(
|
||||||
|
rho,
|
||||||
|
U,
|
||||||
|
phi,
|
||||||
|
thermo
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
#if OPENFOAM_VERSION_MAJOR >= 6
|
||||||
|
Info<< "Creating combustion model\n" << endl;
|
||||||
|
autoPtr<CombustionModel<rhoReactionThermo>> combustion
|
||||||
|
(
|
||||||
|
CombustionModel<rhoReactionThermo>::New(thermo, turbulence())
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
label pRefCell = 0;
|
||||||
|
scalar pRefValue = 0.0;
|
||||||
|
setRefCell(p, pimple.dict(), pRefCell, pRefValue);
|
||||||
|
|
||||||
|
mesh.setFluxRequired(p.name());
|
||||||
|
|
||||||
|
Info<< "Creating field dpdt\n" << endl;
|
||||||
|
volScalarField dpdt
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"dpdt",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("dpdt", p.dimensions()/dimTime, 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "Creating field kinetic energy K\n" << endl;
|
||||||
|
volScalarField K("K", 0.5*magSqr(U));
|
||||||
|
|
||||||
|
#if OPENFOAM_VERSION_MAJOR < 5
|
||||||
|
volScalarField dQ
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"dQ",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("dQ", dimEnergy/dimTime, 0.0)
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
volScalarField Qdot
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"Qdot",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("Qdot", dimEnergy/dimVolume/dimTime, 0.0)
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Info<< "\nReading momentum exchange field Ksl\n" << endl;
|
||||||
|
volScalarField Ksl
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"Ksl",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("0", dimensionSet(1, -3, -1, 0, 0), 0.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
Info<< "Reading particle velocity field Us\n" << endl;
|
||||||
|
volVectorField Us
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"Us",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
volScalarField molarConc
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"molarConc",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("zero",dimensionSet(0, -3, 0, 0, 1),0)
|
||||||
|
);
|
||||||
|
|
||||||
|
volVectorField UsRec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"UsRec",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
Us
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
dimensionedScalar kf("0", dimensionSet(1, 1, -3, -1, 0, 0, 0), 0.026);
|
||||||
|
|
||||||
|
//===============================
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
p = max(p, pMin);
|
||||||
|
p = min(p, pMax);
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
if (UMax.value() > 0)
|
||||||
|
{
|
||||||
|
forAll(U,cellI)
|
||||||
|
{
|
||||||
|
scalar mU(mag(U[cellI]));
|
||||||
|
if (mU > UMax.value())
|
||||||
|
{
|
||||||
|
U[cellI] *= UMax.value() / mU;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
molarConc = 0.0 * molarConc;
|
||||||
|
forAll(Y, i)
|
||||||
|
{
|
||||||
|
volScalarField& Yi = Y[i];
|
||||||
|
dimensionedScalar mi("mi",dimensionSet(1, 0, 0, 0, -1),composition.W(i));
|
||||||
|
mi /= 1000.0; // g to kg
|
||||||
|
molarConc += rho * Yi / mi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
m=gSum(rhoeps*1.0*rhoeps.mesh().V());
|
||||||
|
if(counter==0) m0=m;
|
||||||
|
counter++;
|
||||||
|
Info << "\ncurrent gas mass = " << m << "\n" << endl;
|
||||||
|
Info << "\ncurrent added gas mass = " << m-m0 << "\n" << endl;
|
||||||
|
}
|
||||||
96
applications/solvers/rcfdemSolverRhoSteadyPimpleChem/pEqn.H
Normal file
96
applications/solvers/rcfdemSolverRhoSteadyPimpleChem/pEqn.H
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
rho = thermo.rho();
|
||||||
|
rho = max(rho, rhoMin);
|
||||||
|
rho = min(rho, rhoMax);
|
||||||
|
rho.relax();
|
||||||
|
|
||||||
|
if (stepcounter%nEveryFlow==0)
|
||||||
|
{
|
||||||
|
|
||||||
|
volScalarField rAU(1.0/UEqn.A());
|
||||||
|
surfaceScalarField rhorAUf("rhorAUf", fvc::interpolate(rhoeps*rAU));
|
||||||
|
if (modelType=="A")
|
||||||
|
{
|
||||||
|
rhorAUf *= fvc::interpolate(voidfractionRec);
|
||||||
|
}
|
||||||
|
volVectorField HbyA(constrainHbyA(rAU*UEqn.H(), U, p));
|
||||||
|
|
||||||
|
surfaceScalarField phiUs("phiUs", fvc::interpolate(rhoeps*rAU*Ksl*UsRec)& mesh.Sf());
|
||||||
|
|
||||||
|
|
||||||
|
if (pimple.transonic())
|
||||||
|
{
|
||||||
|
// transonic version not implemented yet
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
surfaceScalarField phiHbyA
|
||||||
|
(
|
||||||
|
"phiHbyA",
|
||||||
|
(
|
||||||
|
fvc::flux(rhoeps*HbyA)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// flux without pressure gradient contribution
|
||||||
|
phi = phiHbyA + phiUs;
|
||||||
|
|
||||||
|
// Update the pressure BCs to ensure flux consistency
|
||||||
|
constrainPressure(p, rhoeps, U, phi, rhorAUf);
|
||||||
|
|
||||||
|
volScalarField SmbyP(particleCloud.chemistryM(0).Sm() / p);
|
||||||
|
|
||||||
|
while (pimple.correctNonOrthogonal())
|
||||||
|
{
|
||||||
|
// Pressure corrector
|
||||||
|
fvScalarMatrix pEqn
|
||||||
|
(
|
||||||
|
fvc::div(phi)
|
||||||
|
- fvm::laplacian(rhorAUf, p)
|
||||||
|
==
|
||||||
|
fvm::Sp(SmbyP, p)
|
||||||
|
+ fvOptions(psi, p, rho.name())
|
||||||
|
);
|
||||||
|
|
||||||
|
pEqn.setReference(pRefCell, pRefValue);
|
||||||
|
|
||||||
|
pEqn.solve();
|
||||||
|
|
||||||
|
if (pimple.finalNonOrthogonalIter())
|
||||||
|
{
|
||||||
|
phi += pEqn.flux();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "rhoEqn.H"
|
||||||
|
#include "compressibleContinuityErrsPU.H"
|
||||||
|
|
||||||
|
// Explicitly relax pressure for momentum corrector
|
||||||
|
p.relax();
|
||||||
|
|
||||||
|
#include "limitP.H"
|
||||||
|
|
||||||
|
// Recalculate density from the relaxed pressure
|
||||||
|
rho = thermo.rho();
|
||||||
|
rho = max(rho, rhoMin);
|
||||||
|
rho = min(rho, rhoMax);
|
||||||
|
rho.relax();
|
||||||
|
Info<< "rho max/min : " << max(rho).value()
|
||||||
|
<< " " << min(rho).value() << endl;
|
||||||
|
|
||||||
|
if (modelType=="A")
|
||||||
|
{
|
||||||
|
U = HbyA - rAU*(voidfractionRec*fvc::grad(p)-Ksl*UsRec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
U = HbyA - rAU*(fvc::grad(p)-Ksl*UsRec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "limitU.H"
|
||||||
|
|
||||||
|
U.correctBoundaryConditions();
|
||||||
|
fvOptions.correct(U);
|
||||||
|
K = 0.5*magSqr(U);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,218 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
License
|
||||||
|
|
||||||
|
This 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.
|
||||||
|
|
||||||
|
This code 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 this code. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria
|
||||||
|
|
||||||
|
Application
|
||||||
|
rcfdemSolverRhoSteadyPimpleChem
|
||||||
|
|
||||||
|
Description
|
||||||
|
Transient (DEM) + steady-state (CFD) solver for compressible flow using the
|
||||||
|
flexible PIMPLE (PISO-SIMPLE) algorithm. Particle-motion is obtained from
|
||||||
|
a recurrence process.
|
||||||
|
Turbulence modelling is generic, i.e. laminar, RAS or LES may be selected.
|
||||||
|
The code is an evolution of the solver rhoPimpleFoam in OpenFOAM(R) 4.x,
|
||||||
|
where additional functionality for CFD-DEM coupling is added.
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "fvCFD.H"
|
||||||
|
//#include "psiThermo.H"
|
||||||
|
#include "turbulentFluidThermoModel.H"
|
||||||
|
#if OPENFOAM_VERSION_MAJOR < 6
|
||||||
|
#include "rhoCombustionModel.H"
|
||||||
|
#else
|
||||||
|
#include "rhoReactionThermo.H"
|
||||||
|
#include "CombustionModel.H"
|
||||||
|
#endif
|
||||||
|
#include "bound.H"
|
||||||
|
#include "pimpleControl.H"
|
||||||
|
#include "fvOptions.H"
|
||||||
|
#include "localEulerDdtScheme.H"
|
||||||
|
#include "fvcSmooth.H"
|
||||||
|
|
||||||
|
#include "cfdemCloudRec.H"
|
||||||
|
#include "recBase.H"
|
||||||
|
#include "recModel.H"
|
||||||
|
#include "recPath.H"
|
||||||
|
|
||||||
|
#include "cfdemCloudEnergy.H"
|
||||||
|
#include "implicitCouple.H"
|
||||||
|
#include "clockModel.H"
|
||||||
|
#include "smoothingModel.H"
|
||||||
|
#include "forceModel.H"
|
||||||
|
#include "thermCondModel.H"
|
||||||
|
#include "energyModel.H"
|
||||||
|
#include "chemistryModel.H"
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
#include "postProcess.H"
|
||||||
|
|
||||||
|
#include "setRootCase.H"
|
||||||
|
#include "createTime.H"
|
||||||
|
#include "createMesh.H"
|
||||||
|
#include "createControl.H"
|
||||||
|
#include "createTimeControls.H"
|
||||||
|
#include "createRDeltaT.H"
|
||||||
|
|
||||||
|
#include "initContinuityErrs.H"
|
||||||
|
#include "createFields.H"
|
||||||
|
//#include "createFieldRefs.H"
|
||||||
|
#include "createFvOptions.H"
|
||||||
|
|
||||||
|
// create cfdemCloud
|
||||||
|
//#include "readGravitationalAcceleration.H"
|
||||||
|
cfdemCloudRec<cfdemCloudEnergy> particleCloud(mesh);
|
||||||
|
#include "checkModelType.H"
|
||||||
|
recBase recurrenceBase(mesh);
|
||||||
|
#include "updateFields.H"
|
||||||
|
|
||||||
|
turbulence->validate();
|
||||||
|
//#include "compressibleCourantNo.H"
|
||||||
|
//#include "setInitialDeltaT.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
label recTimeIndex = 0;
|
||||||
|
scalar recTimeStep = recurrenceBase.recM().recTimeStep();
|
||||||
|
scalar startTime = runTime.startTime().value();
|
||||||
|
|
||||||
|
const IOdictionary& couplingProps = particleCloud.couplingProperties();
|
||||||
|
label nEveryFlow(couplingProps.lookupOrDefault<label>("nEveryFlow",1));
|
||||||
|
Info << "Solving flow equations for U and p every " << nEveryFlow << " steps.\n" << endl;
|
||||||
|
label stepcounter = 0;
|
||||||
|
|
||||||
|
Info<< "\nStarting time loop\n" << endl;
|
||||||
|
|
||||||
|
scalar m(0.0);
|
||||||
|
scalar m0(0.0);
|
||||||
|
label counter(0);
|
||||||
|
p.storePrevIter();
|
||||||
|
|
||||||
|
while (runTime.run())
|
||||||
|
{
|
||||||
|
#include "readTimeControls.H"
|
||||||
|
#include "compressibleCourantNo.H"
|
||||||
|
#include "setDeltaT.H"
|
||||||
|
|
||||||
|
runTime++;
|
||||||
|
|
||||||
|
particleCloud.clockM().start(1,"Global");
|
||||||
|
|
||||||
|
Info<< "Time = " << runTime.timeName() << nl << endl;
|
||||||
|
|
||||||
|
// do particle stuff
|
||||||
|
particleCloud.clockM().start(2,"Coupling");
|
||||||
|
bool hasEvolved = particleCloud.evolve(voidfraction,Us,U);
|
||||||
|
|
||||||
|
//voidfraction = voidfractionRec;
|
||||||
|
//Us = UsRec;
|
||||||
|
|
||||||
|
if(hasEvolved)
|
||||||
|
{
|
||||||
|
particleCloud.smoothingM().smoothen(particleCloud.forceM(0).impParticleForces());
|
||||||
|
}
|
||||||
|
|
||||||
|
Info << "update Ksl.internalField()" << endl;
|
||||||
|
Ksl = particleCloud.momCoupleM(0).impMomSource();
|
||||||
|
Ksl.correctBoundaryConditions();
|
||||||
|
|
||||||
|
//Force Checks
|
||||||
|
vector fTotal(0,0,0);
|
||||||
|
vector fImpTotal = sum(mesh.V()*Ksl.primitiveFieldRef()*(Us.primitiveFieldRef()-U.primitiveFieldRef()));
|
||||||
|
reduce(fImpTotal, sumOp<vector>());
|
||||||
|
Info << "TotalForceExp: " << fTotal << endl;
|
||||||
|
Info << "TotalForceImp: " << fImpTotal << endl;
|
||||||
|
|
||||||
|
#include "solverDebugInfo.H"
|
||||||
|
particleCloud.clockM().stop("Coupling");
|
||||||
|
|
||||||
|
particleCloud.clockM().start(26,"Flow");
|
||||||
|
volScalarField rhoeps("rhoeps",rho*voidfractionRec);
|
||||||
|
|
||||||
|
while (pimple.loop())
|
||||||
|
{
|
||||||
|
// if needed, perform drag update here
|
||||||
|
#if OPENFOAM_VERSION_MAJOR < 6
|
||||||
|
if (pimple.nCorrPIMPLE() <= 1)
|
||||||
|
#else
|
||||||
|
if (pimple.nCorrPimple() <= 1)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#include "rhoEqn.H"
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Pressure-velocity PIMPLE corrector loop
|
||||||
|
|
||||||
|
|
||||||
|
#include "UEqn.H"
|
||||||
|
#include "EEqn.H"
|
||||||
|
|
||||||
|
// --- Pressure corrector loop
|
||||||
|
while (pimple.correct())
|
||||||
|
{
|
||||||
|
// besides this pEqn, OF offers a "pimple consistent"-option
|
||||||
|
#include "molConc.H"
|
||||||
|
#include "pEqn.H"
|
||||||
|
rhoeps=rho*voidfractionRec;
|
||||||
|
}
|
||||||
|
#include "YEqn.H"
|
||||||
|
|
||||||
|
if (pimple.turbCorr())
|
||||||
|
{
|
||||||
|
turbulence->correct();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "monitorMass.H"
|
||||||
|
|
||||||
|
stepcounter++;
|
||||||
|
particleCloud.clockM().stop("Flow");
|
||||||
|
|
||||||
|
particleCloud.clockM().start(31,"postFlow");
|
||||||
|
particleCloud.postFlow();
|
||||||
|
particleCloud.clockM().stop("postFlow");
|
||||||
|
|
||||||
|
particleCloud.clockM().start(32,"ReadFields");
|
||||||
|
if ( runTime.timeOutputValue() - startTime - (recTimeIndex+1)*recTimeStep + 1.0e-5 > 0.0 )
|
||||||
|
{
|
||||||
|
recurrenceBase.updateRecFields();
|
||||||
|
#include "updateFields.H"
|
||||||
|
recTimeIndex++;
|
||||||
|
}
|
||||||
|
particleCloud.clockM().stop("ReadFields");
|
||||||
|
|
||||||
|
runTime.write();
|
||||||
|
|
||||||
|
|
||||||
|
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
|
||||||
|
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
|
||||||
|
<< nl << endl;
|
||||||
|
|
||||||
|
|
||||||
|
particleCloud.clockM().stop("Global");
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< "End\n" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
/*
|
||||||
|
fvScalarMatrix rhoEqn
|
||||||
|
(
|
||||||
|
//fvm::ddt(voidfraction,rho)
|
||||||
|
//+
|
||||||
|
fvc::div(phi)
|
||||||
|
==
|
||||||
|
particleCloud.chemistryM(0).Sm()
|
||||||
|
+ fvOptions(rho)
|
||||||
|
);
|
||||||
|
|
||||||
|
fvOptions.constrain(rhoEqn);
|
||||||
|
|
||||||
|
rhoEqn.solve();
|
||||||
|
|
||||||
|
fvOptions.correct(rho);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -1,4 +1,8 @@
|
|||||||
|
// is it neccessary to extend recurrence path?
|
||||||
|
if(recurrenceBase.recM().endOfPath())
|
||||||
|
{
|
||||||
|
recurrenceBase.extendPath();
|
||||||
|
}
|
||||||
|
|
||||||
recurrenceBase.recM().exportVolScalarField("voidfraction",voidfractionRec);
|
recurrenceBase.recM().exportVolScalarField("voidfraction",voidfractionRec);
|
||||||
recurrenceBase.recM().exportVolVectorField("U",URec);
|
|
||||||
recurrenceBase.recM().exportVolVectorField("Us",UsRec);
|
recurrenceBase.recM().exportVolVectorField("Us",UsRec);
|
||||||
recurrenceBase.recM().exportSurfaceScalarField("phi",phiRec);
|
|
||||||
19
applications/solvers/rctfSpeciesTransport/CEq.H
Executable file
19
applications/solvers/rctfSpeciesTransport/CEq.H
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
volScalarField alphaEff("alphaEff", turbulence->nu()/Sc + alphat);
|
||||||
|
|
||||||
|
CEqn =
|
||||||
|
(
|
||||||
|
fvm::ddt(C)
|
||||||
|
+ fvm::div(phiRec, C)
|
||||||
|
- fvm::laplacian(alphaEff, C)
|
||||||
|
==
|
||||||
|
fvOptions(C)
|
||||||
|
);
|
||||||
|
|
||||||
|
CEqn.relax(relaxCoeff);
|
||||||
|
|
||||||
|
fvOptions.constrain(CEqn);
|
||||||
|
|
||||||
|
CEqn.solve();
|
||||||
|
|
||||||
|
fvOptions.correct(C);
|
||||||
3
applications/solvers/rctfSpeciesTransport/Make/files
Executable file
3
applications/solvers/rctfSpeciesTransport/Make/files
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
rctfSpeciesTransport.C
|
||||||
|
|
||||||
|
EXE=$(CFDEM_APP_DIR)/rctfSpeciesTransport
|
||||||
27
applications/solvers/rctfSpeciesTransport/Make/options
Executable file
27
applications/solvers/rctfSpeciesTransport/Make/options
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
include $(CFDEM_ADD_LIBS_DIR)/additionalLibs
|
||||||
|
|
||||||
|
EXE_INC = \
|
||||||
|
-I$(CFDEM_OFVERSION_DIR) \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
|
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
|
||||||
|
-I$(LIB_SRC)/TurbulenceModels/incompressible/lnInclude \
|
||||||
|
-I$(LIB_SRC)/transportModels \
|
||||||
|
-I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
|
||||||
|
-I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/lnInclude \
|
||||||
|
-I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/cfdTools \
|
||||||
|
-I$(CFDEM_SRC_DIR)/recurrence/lnInclude \
|
||||||
|
-I$(CFDEM_SRC_DIR)/lagrangian/cfdemParticle/derived/cfdemCloudRec \
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-L$(CFDEM_LIB_DIR)\
|
||||||
|
-lrecurrence \
|
||||||
|
-lturbulenceModels \
|
||||||
|
-lincompressibleTurbulenceModels \
|
||||||
|
-lincompressibleTransportModels \
|
||||||
|
-lfiniteVolume \
|
||||||
|
-lmeshTools \
|
||||||
|
-lfvOptions \
|
||||||
|
-l$(CFDEM_LIB_NAME) \
|
||||||
|
$(CFDEM_ADD_LIB_PATHS) \
|
||||||
|
$(CFDEM_ADD_LIBS)
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
// calculate the continuity error according to phiRec
|
||||||
|
|
||||||
|
{
|
||||||
|
volScalarField contErr(fvc::div(phiRec));
|
||||||
|
|
||||||
|
scalar sumLocalContErr = runTime.deltaTValue()*
|
||||||
|
mag(contErr)().weightedAverage(mesh.V()).value();
|
||||||
|
|
||||||
|
scalar globalContErr = runTime.deltaTValue()*
|
||||||
|
contErr.weightedAverage(mesh.V()).value();
|
||||||
|
cumulativeContErr += globalContErr;
|
||||||
|
|
||||||
|
Info<< "time step continuity errors : sum local = " << sumLocalContErr
|
||||||
|
<< ", global = " << globalContErr
|
||||||
|
<< ", cumulative = " << cumulativeContErr
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
281
applications/solvers/rctfSpeciesTransport/createFields.H
Executable file
281
applications/solvers/rctfSpeciesTransport/createFields.H
Executable file
@ -0,0 +1,281 @@
|
|||||||
|
//creating the fields according to the recurrence dictionary
|
||||||
|
|
||||||
|
IOdictionary recProperties_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"recProperties0",
|
||||||
|
runTime.constant(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
List<wordList> fieldsDict_(recProperties_.lookup("fieldsPairs"));
|
||||||
|
|
||||||
|
wordList fieldNames(fieldsDict_.size());
|
||||||
|
|
||||||
|
for(int i = 0; i < fieldsDict_.size(); i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
fieldNames[i]= fieldsDict_[i][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< "\n list of the fields: \n" << fieldNames << endl;
|
||||||
|
|
||||||
|
//reading coherent velocity field name
|
||||||
|
label k = findIndex(fieldNames,"coh_velocity");
|
||||||
|
|
||||||
|
if (k < 0)
|
||||||
|
{
|
||||||
|
FatalError <<"\n No field is defiened for the coherent velocity\n" << abort(FatalError);
|
||||||
|
}
|
||||||
|
const word Ucoh_pair = fieldsDict_[k][1];
|
||||||
|
|
||||||
|
volVectorField UcohRec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
Ucoh_pair,
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedVector("zero",dimensionSet(0, 1, -1, 0, 0),vector::zero)
|
||||||
|
);
|
||||||
|
|
||||||
|
//reading incoherent velocity field name
|
||||||
|
k = findIndex(fieldNames,"inc_velocity");
|
||||||
|
|
||||||
|
if (k < 0)
|
||||||
|
{
|
||||||
|
FatalError <<"\n No field is defiened for the incoherent velocity\n" << abort(FatalError);
|
||||||
|
}
|
||||||
|
const word Uinc_pair = fieldsDict_[k][1];
|
||||||
|
|
||||||
|
volVectorField UincRec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
Uinc_pair,
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedVector("zero",dimensionSet(0, 1, -1, 0, 0),vector::zero)
|
||||||
|
);
|
||||||
|
|
||||||
|
//reading coherent turb kinetic energy field name
|
||||||
|
k = findIndex(fieldNames,"kSGS_coh");
|
||||||
|
if (k < 0)
|
||||||
|
{
|
||||||
|
FatalError <<"\n No field is defiened for the coherent subgrid-scale turbulent kinetic energy\n" << abort(FatalError);
|
||||||
|
}
|
||||||
|
const word kSGScoh_pair = fieldsDict_[k][1];
|
||||||
|
|
||||||
|
volScalarField kcohRec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
kSGScoh_pair,
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("zero",dimensionSet(0, 2, -2, 0, 0),0.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
//reading incoherent turb kinetic energy field name
|
||||||
|
k = findIndex(fieldNames,"kSGS_inc");
|
||||||
|
if (k < 0)
|
||||||
|
{
|
||||||
|
FatalError <<"\n No field is defiened for the coherent subgrid-scale turbulent kinetic energy\n" << abort(FatalError);
|
||||||
|
}
|
||||||
|
const word kSGSinc_pair = fieldsDict_[k][1];
|
||||||
|
|
||||||
|
volScalarField kincRec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
kSGSinc_pair,
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("zero",dimensionSet(0, 2, -2, 0, 0),0.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
// calculated fields
|
||||||
|
Info<< "\nCreating cell volume field\n" << endl;
|
||||||
|
|
||||||
|
volScalarField delta
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"delta",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedScalar("delta", dimLength, 0.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
delta.primitiveFieldRef()=pow(mesh.V(),1.0/3.0);
|
||||||
|
delta.write();
|
||||||
|
|
||||||
|
|
||||||
|
volVectorField URec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"URec",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
Info<< "\nCreating turb kinetic energy field\n" << endl;
|
||||||
|
|
||||||
|
volScalarField kRec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"kRec",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
kcohRec+kincRec
|
||||||
|
);
|
||||||
|
|
||||||
|
// check if there is any negative values
|
||||||
|
forAll(kRec, cellI)
|
||||||
|
{
|
||||||
|
if (kRec[cellI] < SMALL)
|
||||||
|
{
|
||||||
|
kRec[cellI] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const fvPatchList& patches = mesh.boundary();
|
||||||
|
forAll(patches, patchI)
|
||||||
|
{
|
||||||
|
kRec.boundaryFieldRef()[patchI] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
kRec.write();
|
||||||
|
|
||||||
|
Info<< "\nCreating turb viscosity field\n" << endl;
|
||||||
|
volScalarField nutRec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"nutRec",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
sqrt(kRec)*delta*0.094
|
||||||
|
);
|
||||||
|
|
||||||
|
nutRec.write();
|
||||||
|
|
||||||
|
|
||||||
|
Info<< "Calculating face flux field phiRec\n" << endl;
|
||||||
|
surfaceScalarField phiRec
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"phiRec",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
linearInterpolate(URec) & mesh.Sf()
|
||||||
|
);
|
||||||
|
|
||||||
|
phiRec.write();
|
||||||
|
|
||||||
|
singlePhaseTransportModel laminarTransport(URec, phiRec);
|
||||||
|
|
||||||
|
autoPtr<incompressible::turbulenceModel> turbulence
|
||||||
|
(
|
||||||
|
incompressible::turbulenceModel::New(URec, phiRec, laminarTransport)
|
||||||
|
);
|
||||||
|
|
||||||
|
dimensionedScalar Sc("Sc", dimless, laminarTransport);
|
||||||
|
dimensionedScalar Sct("Sct", dimless, laminarTransport);
|
||||||
|
|
||||||
|
volScalarField alphat
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"alphat",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
nutRec/Sct
|
||||||
|
);
|
||||||
|
|
||||||
|
// create the scalar field
|
||||||
|
Info<< "Creating scalar transport field\n" << endl;
|
||||||
|
|
||||||
|
volScalarField C
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"C",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
fvScalarMatrix CEqn(C, dimless*dimVolume/(dimTime));
|
||||||
|
|
||||||
|
scalar relaxCoeff(0.0);
|
||||||
|
|
||||||
|
Info<< "reading clockProperties\n" << endl;
|
||||||
|
|
||||||
|
IOdictionary clockProperties
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"clockProperties",
|
||||||
|
mesh.time().constant(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
autoPtr<clockModel> myClock
|
||||||
|
(
|
||||||
|
clockModel::New
|
||||||
|
(
|
||||||
|
clockProperties,
|
||||||
|
mesh.time()
|
||||||
|
)
|
||||||
|
);
|
||||||
66
applications/solvers/rctfSpeciesTransport/createRecBase.H
Normal file
66
applications/solvers/rctfSpeciesTransport/createRecBase.H
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// check which recProperties dicts are present, read them in and construct a PtrList of recBases
|
||||||
|
// names for dicts can be "recProperties" or "recPropertiesN" where N in {0, 1, ...}
|
||||||
|
|
||||||
|
#include "error.H"
|
||||||
|
|
||||||
|
word dictName = "recProperties";
|
||||||
|
wordList recPropertiesList(0);
|
||||||
|
PtrList <recBase> recBases(0);
|
||||||
|
label maxDictNumber = 100;
|
||||||
|
|
||||||
|
{
|
||||||
|
IOdictionary recPropDict
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
dictName,
|
||||||
|
mesh.time().constant(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (recPropDict.headerOk())
|
||||||
|
{
|
||||||
|
recPropertiesList.append(dictName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (label counter = 0; counter < maxDictNumber; counter++)
|
||||||
|
{
|
||||||
|
word dictNameIter = dictName + Foam::name(counter);
|
||||||
|
IOdictionary recPropDict
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
dictNameIter,
|
||||||
|
mesh.time().constant(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (recPropDict.headerOk())
|
||||||
|
{
|
||||||
|
recPropertiesList.append(dictNameIter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recPropertiesList.size() == 0)
|
||||||
|
{
|
||||||
|
FatalError << "no recProperties dicts found" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Info << "found " << recPropertiesList.size() << " dicts with names " << recPropertiesList << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (label counter = 0; counter < recPropertiesList.size(); counter++)
|
||||||
|
{
|
||||||
|
recBases.append( new recBase(mesh, recPropertiesList[counter]));
|
||||||
|
}
|
||||||
131
applications/solvers/rctfSpeciesTransport/rctfSpeciesTransport.C
Executable file
131
applications/solvers/rctfSpeciesTransport/rctfSpeciesTransport.C
Executable file
@ -0,0 +1,131 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
CFDEMcoupling academic - Open Source CFD-DEM coupling
|
||||||
|
|
||||||
|
Contributing authors:
|
||||||
|
Thomas Lichtenegger, Gerhard Holzinger, Sanaz Abbasi
|
||||||
|
Copyright (C) 2015- Johannes Kepler University, Linz
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of CFDEMcoupling academic.
|
||||||
|
|
||||||
|
CFDEMcoupling academic 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.
|
||||||
|
|
||||||
|
CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Application
|
||||||
|
Turbulent Transport Recurrence Solver for modal decomposition
|
||||||
|
|
||||||
|
Description
|
||||||
|
Solves a transport equation for a passive scalar on a single-phase solution
|
||||||
|
for a solver based on recurrence statistics
|
||||||
|
|
||||||
|
Rules
|
||||||
|
Solution data to compute the recurrence statistics from, needs to
|
||||||
|
reside in $CASE_ROOT/dataBase(0...N)
|
||||||
|
Time step data in the first dataBase needs to be evenly spaced in time
|
||||||
|
A list of indices for the corresponding incoherent fields to coherent ones
|
||||||
|
should be provided.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "fvCFD.H"
|
||||||
|
#include "singlePhaseTransportModel.H"
|
||||||
|
#include "turbulentTransportModel.H"
|
||||||
|
#include "fvOptions.H"
|
||||||
|
|
||||||
|
#include "recBase.H"
|
||||||
|
#include "recModel.H"
|
||||||
|
|
||||||
|
#include "clockModel.H"
|
||||||
|
|
||||||
|
#include "objectRegistry.H"
|
||||||
|
#include "VectorSpace.H"
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
#include "postProcess.H"
|
||||||
|
#include "setRootCase.H"
|
||||||
|
#include "createTime.H"
|
||||||
|
#include "createMesh.H"
|
||||||
|
#include "createControl.H"
|
||||||
|
#include "createFields.H"
|
||||||
|
#include "createFvOptions.H"
|
||||||
|
scalar cumulativeContErr = 0;
|
||||||
|
|
||||||
|
//create recBases according to a list of recProperties
|
||||||
|
#include "createRecBase.H"
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
label recTimeIndex(0);
|
||||||
|
label currTimeIndex(0);
|
||||||
|
|
||||||
|
scalar recTimeStep_=recBases[0].recM().recTimeStep();
|
||||||
|
labelPairList incPairTimeIndex_(0);
|
||||||
|
|
||||||
|
IFstream pairFile("incIndexPairList");
|
||||||
|
pairFile >> incPairTimeIndex_;
|
||||||
|
|
||||||
|
while (runTime.run())
|
||||||
|
{
|
||||||
|
|
||||||
|
myClock().start(1,"Global");
|
||||||
|
runTime++;
|
||||||
|
|
||||||
|
myClock().start(11,"Total");
|
||||||
|
|
||||||
|
Info<< "Time = " << runTime.timeName() << nl << endl;
|
||||||
|
|
||||||
|
myClock().start(2,"fieldUpdate");
|
||||||
|
|
||||||
|
if ( runTime.timeOutputValue() - (recTimeIndex+1)*recTimeStep_ + 1.0e-5 > 0.0 )
|
||||||
|
{
|
||||||
|
Info << "Updating fields at run time " << runTime.timeOutputValue()
|
||||||
|
<< " corresponding to recurrence time " << (recTimeIndex+1)*recTimeStep_ << ".\n" << endl;
|
||||||
|
recBases[0].updateRecFields();
|
||||||
|
#include "readFields.H"
|
||||||
|
|
||||||
|
recTimeIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
myClock().stop("fieldUpdate");
|
||||||
|
|
||||||
|
#include "continuityErrCalc.H"
|
||||||
|
|
||||||
|
myClock().start(3,"speciesEqn");
|
||||||
|
#include "CEq.H"
|
||||||
|
myClock().stop("speciesEqn");
|
||||||
|
|
||||||
|
myClock().stop("Total");
|
||||||
|
|
||||||
|
runTime.write();
|
||||||
|
|
||||||
|
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
|
||||||
|
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
|
||||||
|
<< nl << endl;
|
||||||
|
|
||||||
|
myClock().stop("Global");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
myClock().evalPar();
|
||||||
|
myClock().normHist();
|
||||||
|
|
||||||
|
Info<< "End\n" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
40
applications/solvers/rctfSpeciesTransport/readFields.H
Executable file
40
applications/solvers/rctfSpeciesTransport/readFields.H
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
currTimeIndex = recBases[0].recM().currentTimeIndex();
|
||||||
|
|
||||||
|
Info << "current Time Index = " << currTimeIndex << endl;
|
||||||
|
|
||||||
|
recBases[0].recM().exportVolVectorField(Ucoh_pair,UcohRec);
|
||||||
|
recBases[0].recM().exportVolScalarField(kSGScoh_pair,kcohRec);
|
||||||
|
|
||||||
|
|
||||||
|
label incTimeIndex = incPairTimeIndex_[currTimeIndex][1];
|
||||||
|
|
||||||
|
Info << " incoherent pair Time Index = " << incTimeIndex << endl;
|
||||||
|
|
||||||
|
UincRec = recBases[1].recM().exportVolVectorField(Uinc_pair,incTimeIndex);
|
||||||
|
kincRec = recBases[1].recM().exportVolScalarField(kSGSinc_pair,incTimeIndex);
|
||||||
|
|
||||||
|
kRec = kcohRec+kincRec;
|
||||||
|
|
||||||
|
forAll(kRec, cellI)
|
||||||
|
{
|
||||||
|
if (kRec[cellI] < SMALL)
|
||||||
|
{
|
||||||
|
kRec[cellI] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fvPatchList& patches = mesh.boundary();
|
||||||
|
forAll(patches, patchI)
|
||||||
|
{
|
||||||
|
kRec.boundaryFieldRef()[patchI] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
URec = UcohRec + UincRec;
|
||||||
|
phiRec = linearInterpolate(URec) & mesh.Sf();
|
||||||
|
|
||||||
|
nutRec = sqrt(kRec)*delta*0.094;
|
||||||
|
|
||||||
|
alphat = nutRec/Sct;
|
||||||
|
alphat.correctBoundaryConditions();
|
||||||
|
|
||||||
3
applications/utilities/displacementField/Make/files
Normal file
3
applications/utilities/displacementField/Make/files
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
displacementField.C
|
||||||
|
|
||||||
|
EXE = $(CFDEM_APP_DIR)/displacementField
|
||||||
7
applications/utilities/displacementField/Make/options
Normal file
7
applications/utilities/displacementField/Make/options
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-lfiniteVolume \
|
||||||
|
-lmeshTools
|
||||||
458
applications/utilities/displacementField/displacementField.C
Normal file
458
applications/utilities/displacementField/displacementField.C
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration | Website: https://openfoam.org
|
||||||
|
\\ / A nd | Copyright (C) 2011-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/>.
|
||||||
|
|
||||||
|
Application
|
||||||
|
displacementField
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "fvCFD.H"
|
||||||
|
#include "vectorList.H"
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
void findPairs(labelList &, labelList &, labelPairList &);
|
||||||
|
void findPairsUnordered(labelList &, labelList &, labelPairList &);
|
||||||
|
void fillEmptyCells(fvMesh &, label , labelList &, volVectorField &, volVectorField &, scalarList &, vector, vector, bool, scalar);
|
||||||
|
void nearestNeighborCells(fvMesh &, label, label, labelList &, labelList &);
|
||||||
|
void normalizeFields(labelList &, volVectorField &, volVectorField &);
|
||||||
|
void readDump(std::string, labelList &, vectorList &);
|
||||||
|
scalar weightFun(scalar);
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
argList::addOption
|
||||||
|
(
|
||||||
|
"totalProcs",
|
||||||
|
"label",
|
||||||
|
"total number of parallel processes, defaults to 1"
|
||||||
|
);
|
||||||
|
argList::addOption
|
||||||
|
(
|
||||||
|
"thisProc",
|
||||||
|
"label",
|
||||||
|
"number of current process, defaults to 0"
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
#include "setRootCase.H"
|
||||||
|
#include "createTime.H"
|
||||||
|
#include "createMesh.H"
|
||||||
|
|
||||||
|
const label thisProc = args.optionLookupOrDefault("thisProc", 0);
|
||||||
|
const label totalProcs = args.optionLookupOrDefault("totalProcs", 1);
|
||||||
|
|
||||||
|
Info << "This is number " << thisProc << " of " << totalProcs << " processes." << endl;
|
||||||
|
|
||||||
|
|
||||||
|
// user-defined input for each case
|
||||||
|
IOdictionary displacementProperties
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"displacementProperties",
|
||||||
|
mesh.time().constant(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
label dumpIndexStart(readLabel(displacementProperties.lookup("dumpIndexStart")));
|
||||||
|
label dumpIndexEnd(readLabel(displacementProperties.lookup("dumpIndexEnd")));
|
||||||
|
label dumpIndexInputIncrement(readLabel(displacementProperties.lookup("dumpIndexInputIncrement")));
|
||||||
|
label dumpIndexDisplacementIncrement(readLabel(displacementProperties.lookup("dumpIndexDisplacementIncrement")));
|
||||||
|
label nNeighMin(readLabel(displacementProperties.lookup("nNeighMin")));
|
||||||
|
scalar timePerInputStep(readScalar(displacementProperties.lookup("timePerInputStep")));
|
||||||
|
scalar timePerDisplacementStep(readScalar(displacementProperties.lookup("timePerDisplacementStep")));
|
||||||
|
scalar startTime(readScalar(displacementProperties.lookup("startTime")));
|
||||||
|
std::string filepath=string(displacementProperties.lookup("filepath"));
|
||||||
|
std::string fileext=string(displacementProperties.lookupOrDefault<string>("fileextension",""));
|
||||||
|
bool interpolate=bool(displacementProperties.lookupOrDefault<bool>("fillEmptyCells",true));
|
||||||
|
bool averageMode=bool(displacementProperties.lookupOrDefault<bool>("averageMode",false));
|
||||||
|
vector defaultUs=vector(displacementProperties.lookupOrDefault<vector>("defaultUs",vector::zero));
|
||||||
|
vector defaultUsDirectedVariance=vector(displacementProperties.lookupOrDefault<vector>("defaultUsDirectedVariance",vector::zero));
|
||||||
|
|
||||||
|
scalar xmin=scalar(displacementProperties.lookupOrDefault<scalar>("xmin",-1e10));
|
||||||
|
scalar xmax=scalar(displacementProperties.lookupOrDefault<scalar>("xmax",1e10));
|
||||||
|
scalar ymin=scalar(displacementProperties.lookupOrDefault<scalar>("ymin",-1e10));
|
||||||
|
scalar ymax=scalar(displacementProperties.lookupOrDefault<scalar>("ymax",1e10));
|
||||||
|
scalar zmin=scalar(displacementProperties.lookupOrDefault<scalar>("zmin",-1e10));
|
||||||
|
scalar zmax=scalar(displacementProperties.lookupOrDefault<scalar>("zmax",1e10));
|
||||||
|
scalarList boundaries(6);
|
||||||
|
boundaries[0]=xmin;
|
||||||
|
boundaries[1]=xmax;
|
||||||
|
boundaries[2]=ymin;
|
||||||
|
boundaries[3]=ymax;
|
||||||
|
boundaries[4]=zmin;
|
||||||
|
boundaries[5]=zmax;
|
||||||
|
|
||||||
|
vectorList probePoints=vectorList(displacementProperties.lookupOrDefault<vectorList>("probePoints",vectorList(0)));
|
||||||
|
bool monitorProbes = false;
|
||||||
|
if (probePoints.size()>0) monitorProbes = true;
|
||||||
|
#include "OFstream.H"
|
||||||
|
OFstream monitoringDataFile("monitoringData.txt");
|
||||||
|
if (monitorProbes)
|
||||||
|
{
|
||||||
|
monitoringDataFile << "# monitoring data file" << endl;
|
||||||
|
monitoringDataFile << "# format: time nPerCell[p1] UDisp[p1] UDispDirectedVariance[p1] nPerCell[p2] ... " << endl;
|
||||||
|
for(label p=0;p<probePoints.size();p++)
|
||||||
|
{
|
||||||
|
vector pos = probePoints[p];
|
||||||
|
monitoringDataFile << "# point[" << p << "] = " << pos << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
label dumpIndex1 = dumpIndexStart + thisProc * dumpIndexInputIncrement;
|
||||||
|
label dumpIndex2 = dumpIndex1 + dumpIndexDisplacementIncrement;
|
||||||
|
|
||||||
|
volVectorField Us
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"UDisp",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedVector("zero", dimensionSet(0,1,-1,0,0), vector::zero)
|
||||||
|
);
|
||||||
|
|
||||||
|
volVectorField UsDirectedVariance
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"UDispDirectedVariance",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
dimensionedVector("zero", dimensionSet(0,1,-1,0,0), vector::zero)
|
||||||
|
);
|
||||||
|
|
||||||
|
labelList particlesInCell(mesh.nCells(), 0);
|
||||||
|
|
||||||
|
scalar currTime=startTime + thisProc * timePerInputStep;
|
||||||
|
label timeIndex=thisProc;
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
runTime.setTime(currTime,timeIndex);
|
||||||
|
// read dump files and check which particle indices are present in both
|
||||||
|
labelList indices1, indices2;
|
||||||
|
vectorList positions1, positions2;
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << filepath << dumpIndex1 << fileext;
|
||||||
|
std::string filename1 = ss.str();
|
||||||
|
ss.str("");
|
||||||
|
ss << filepath << dumpIndex2 << fileext;
|
||||||
|
std::string filename2 = ss.str();
|
||||||
|
|
||||||
|
if (access( filename1.c_str(), F_OK ) == -1 || access( filename2.c_str(), F_OK ) == -1 || dumpIndex2 > dumpIndexEnd)
|
||||||
|
{
|
||||||
|
if (averageMode)
|
||||||
|
{
|
||||||
|
normalizeFields(particlesInCell, Us, UsDirectedVariance);
|
||||||
|
fillEmptyCells(mesh,nNeighMin,particlesInCell,Us,UsDirectedVariance,boundaries,defaultUs,defaultUsDirectedVariance,interpolate,timePerDisplacementStep);
|
||||||
|
|
||||||
|
Us /= timePerDisplacementStep;
|
||||||
|
UsDirectedVariance /= timePerDisplacementStep;
|
||||||
|
Us.write();
|
||||||
|
UsDirectedVariance.write();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info << "\nReading" << endl;
|
||||||
|
Info << "\t" << filename1 << endl;
|
||||||
|
Info << "\t" << filename2 << endl;
|
||||||
|
Info << "corresponding to time = " << currTime << "." << endl;
|
||||||
|
|
||||||
|
readDump(filename1, indices1, positions1);
|
||||||
|
readDump(filename2, indices2, positions2);
|
||||||
|
|
||||||
|
labelPairList pairs;
|
||||||
|
findPairs(indices1,indices2,pairs);
|
||||||
|
|
||||||
|
// average particle displacements and their variance
|
||||||
|
Info << "Binning particle displacements on mesh." << endl;
|
||||||
|
vector position, displacement;
|
||||||
|
label line1, line2;
|
||||||
|
label cellI;
|
||||||
|
|
||||||
|
if (!averageMode)
|
||||||
|
{
|
||||||
|
Us *= 0.0;
|
||||||
|
UsDirectedVariance *= 0.0;
|
||||||
|
particlesInCell.clear();
|
||||||
|
particlesInCell.setSize(mesh.nCells(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (label partI = 0; partI < pairs.size(); partI++)
|
||||||
|
{
|
||||||
|
line1 = pairs[partI].first();
|
||||||
|
line2 = pairs[partI].second();
|
||||||
|
position = positions1[line1];
|
||||||
|
displacement = positions2[line2] - positions1[line1];
|
||||||
|
cellI = mesh.findCell(position);
|
||||||
|
if (cellI < 0) continue;
|
||||||
|
particlesInCell[cellI] += 1;
|
||||||
|
Us[cellI] += displacement;
|
||||||
|
|
||||||
|
for (label comp=0;comp<3;comp++)
|
||||||
|
{
|
||||||
|
UsDirectedVariance[cellI].component(comp) += displacement.component(comp)*displacement.component(comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!averageMode)
|
||||||
|
{
|
||||||
|
normalizeFields(particlesInCell, Us, UsDirectedVariance);
|
||||||
|
fillEmptyCells(mesh,nNeighMin,particlesInCell,Us,UsDirectedVariance,boundaries,defaultUs,defaultUsDirectedVariance,interpolate,timePerDisplacementStep);
|
||||||
|
|
||||||
|
Us /= timePerDisplacementStep;
|
||||||
|
UsDirectedVariance /= timePerDisplacementStep;
|
||||||
|
Us.write();
|
||||||
|
UsDirectedVariance.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (averageMode && monitorProbes)
|
||||||
|
{
|
||||||
|
monitoringDataFile << currTime << " ";
|
||||||
|
for(label p=0;p<probePoints.size();p++)
|
||||||
|
{
|
||||||
|
vector pos = probePoints[p];
|
||||||
|
label cellP = mesh.findCell(pos);
|
||||||
|
monitoringDataFile << " " << particlesInCell[cellP] << " " << Us[cellP]/timePerDisplacementStep << " " << UsDirectedVariance[cellP]/(timePerDisplacementStep*timePerDisplacementStep);
|
||||||
|
}
|
||||||
|
monitoringDataFile << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
dumpIndex1 += dumpIndexInputIncrement*totalProcs;
|
||||||
|
dumpIndex2 += dumpIndexInputIncrement*totalProcs;
|
||||||
|
currTime += timePerInputStep*totalProcs;
|
||||||
|
timeIndex += totalProcs;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void readDump(std::string filename, labelList &indices, vectorList &positions)
|
||||||
|
{
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
const label leadingLines = 9;
|
||||||
|
label lineCounter = 0;
|
||||||
|
label partIndex;
|
||||||
|
scalar x, y, z;
|
||||||
|
|
||||||
|
indices.clear();
|
||||||
|
positions.clear();
|
||||||
|
|
||||||
|
std::ifstream file(filename);
|
||||||
|
std::string str;
|
||||||
|
while (std::getline(file, str))
|
||||||
|
{
|
||||||
|
if (lineCounter >= leadingLines)
|
||||||
|
{
|
||||||
|
sscanf(str.c_str(), "%d %lf %lf %lf", &partIndex, &x, &y, &z);
|
||||||
|
indices.append(partIndex);
|
||||||
|
positions.append(vector(x,y,z));
|
||||||
|
}
|
||||||
|
lineCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void findPairs(labelList &indices1, labelList &indices2, labelPairList &pairs)
|
||||||
|
{
|
||||||
|
// remove all entries from first list if they are not present in second list
|
||||||
|
// this assumes ordered entries
|
||||||
|
|
||||||
|
if (indices2.size() == 0) return;
|
||||||
|
|
||||||
|
for (label i=0;i<indices1.size();i++)
|
||||||
|
{
|
||||||
|
label j1 = -1;
|
||||||
|
label j2 = indices2.size();
|
||||||
|
label jmid = 0;
|
||||||
|
label index1 = indices1[i];
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
jmid = (j1+j2)/2;
|
||||||
|
if (indices2[jmid] > index1) j2 = jmid;
|
||||||
|
else if (indices2[jmid] < index1) j1 = jmid;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pairs.append(labelPair(i,jmid));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j2-j1 == 1) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Info << "findPairs: " << pairs.size() << " pairs found." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void findPairsUnordered(labelList &indices1, labelList &indices2, labelPairList &pairs)
|
||||||
|
{
|
||||||
|
// remove all entries from first list if they are not present in second list
|
||||||
|
|
||||||
|
for (label i=0;i<indices1.size();i++)
|
||||||
|
{
|
||||||
|
for (label j=0;j<indices2.size();j++)
|
||||||
|
{
|
||||||
|
if (indices1[i] == indices2[j])
|
||||||
|
{
|
||||||
|
pairs.append(labelPair(i,j));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Info << "findPairs: " << pairs.size() << " pairs found." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillEmptyCells(fvMesh &mesh, label nNeighMin, labelList &particlesInCell, volVectorField &Us, volVectorField& UsDirectedVariance,scalarList& boundaries, vector defaultUs, vector defaultUsDirectedVariance, bool interpolate, scalar dt)
|
||||||
|
{
|
||||||
|
labelList neighborsWithValues;
|
||||||
|
scalar neighborSqrDistance;
|
||||||
|
scalar weight;
|
||||||
|
scalar weightSum;
|
||||||
|
scalarList weights;
|
||||||
|
|
||||||
|
Info << "Filling empty cells." << endl;
|
||||||
|
forAll(mesh.C(), cellI)
|
||||||
|
{
|
||||||
|
if (particlesInCell[cellI] > 0) continue;
|
||||||
|
|
||||||
|
vector position = mesh.C()[cellI];
|
||||||
|
label outsideBox = 0;
|
||||||
|
if (position.x() < boundaries[0] || position.x() > boundaries[1]) outsideBox++;
|
||||||
|
if (position.y() < boundaries[2] || position.y() > boundaries[3]) outsideBox++;
|
||||||
|
if (position.z() < boundaries[4] || position.z() > boundaries[5]) outsideBox++;
|
||||||
|
|
||||||
|
if (outsideBox > 0 || !interpolate)
|
||||||
|
{
|
||||||
|
Us[cellI] = defaultUs*dt;
|
||||||
|
UsDirectedVariance[cellI] = defaultUsDirectedVariance*dt;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nearestNeighborCells(mesh, cellI, nNeighMin, particlesInCell, neighborsWithValues);
|
||||||
|
weightSum = 0.0;
|
||||||
|
weights.clear();
|
||||||
|
for (label neighI=0; neighI<neighborsWithValues.size(); neighI++)
|
||||||
|
{
|
||||||
|
neighborSqrDistance = magSqr(mesh.C()[cellI] - mesh.C()[neighborsWithValues[neighI]]);
|
||||||
|
weight = weightFun(neighborSqrDistance);
|
||||||
|
weights.append(weight);
|
||||||
|
weightSum += weight;
|
||||||
|
}
|
||||||
|
for (label neighI=0; neighI<neighborsWithValues.size(); neighI++)
|
||||||
|
{
|
||||||
|
weight = weights[neighI]/weightSum;
|
||||||
|
Us[cellI] += weight*Us[neighborsWithValues[neighI]];
|
||||||
|
UsDirectedVariance[cellI] += weight*UsDirectedVariance[neighborsWithValues[neighI]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure no particles are placed outside of domain
|
||||||
|
// TODO: correct following implementation (meshSearch) and test it
|
||||||
|
/*
|
||||||
|
vector shiftedPosition = position + dt * Us[cellI];
|
||||||
|
label cellJ = mesh.findCell(shiftedPosition);
|
||||||
|
if (cellJ < 0)
|
||||||
|
{
|
||||||
|
label cellK = mesh.findNearestCellWalk(shiftedPosition,cellI);
|
||||||
|
Us[cellI] = (mesh.C()[cellI] - mesh.C()[cellK]) / dt;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nearestNeighborCells(fvMesh &mesh, label refCell, label nNeighMin, labelList &particlesInCell, labelList &neighborsWithValues)
|
||||||
|
{
|
||||||
|
std::set<label> neighbors;
|
||||||
|
std::set<label> newNeighbors;
|
||||||
|
std::set<label> recentNeighbors;
|
||||||
|
|
||||||
|
neighbors.insert(refCell);
|
||||||
|
recentNeighbors.insert(refCell);
|
||||||
|
|
||||||
|
neighborsWithValues.clear();
|
||||||
|
|
||||||
|
while(neighborsWithValues.size() < nNeighMin)
|
||||||
|
{
|
||||||
|
for (std::set<label>::iterator it=recentNeighbors.begin(); it!=recentNeighbors.end(); ++it)
|
||||||
|
{
|
||||||
|
labelList adjacent = mesh.cellCells()[*it];
|
||||||
|
label adj;
|
||||||
|
for (label j=0; j<adjacent.size(); j++)
|
||||||
|
{
|
||||||
|
adj = adjacent[j];
|
||||||
|
std::set<label>::iterator it2 = neighbors.find(adj);
|
||||||
|
if (it2 == neighbors.end())
|
||||||
|
{
|
||||||
|
newNeighbors.insert(adj);
|
||||||
|
neighbors.insert(adj);
|
||||||
|
if (particlesInCell[adj] > 0) neighborsWithValues.append(adj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newNeighbors.size() == 0) return;
|
||||||
|
recentNeighbors.clear();
|
||||||
|
recentNeighbors = newNeighbors;
|
||||||
|
newNeighbors.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void normalizeFields(labelList& particlesInCell, volVectorField& Us, volVectorField & UsDirectedVariance)
|
||||||
|
{
|
||||||
|
for (label cellJ = 0; cellJ<particlesInCell.size(); cellJ++)
|
||||||
|
{
|
||||||
|
if (particlesInCell[cellJ] > 0)
|
||||||
|
{
|
||||||
|
Us[cellJ] /= particlesInCell[cellJ];
|
||||||
|
UsDirectedVariance[cellJ] /= particlesInCell[cellJ];
|
||||||
|
for (label comp=0;comp<3;comp++)
|
||||||
|
{
|
||||||
|
UsDirectedVariance[cellJ].component(comp) -= Us[cellJ].component(comp)*Us[cellJ].component(comp);
|
||||||
|
if (UsDirectedVariance[cellJ].component(comp) > 0) UsDirectedVariance[cellJ].component(comp) = Foam::sqrt(UsDirectedVariance[cellJ].component(comp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scalar weightFun(scalar distSqr)
|
||||||
|
{
|
||||||
|
// inverse distance weighting, order 2
|
||||||
|
return 1.0/distSqr;
|
||||||
|
}
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
rBaseMirror.C
|
||||||
|
|
||||||
|
EXE=$(CFDEM_APP_DIR)/rBaseMirror
|
||||||
@ -13,5 +13,7 @@
|
|||||||
vector refPoint(mirrorProperties.lookup("refPoint"));
|
vector refPoint(mirrorProperties.lookup("refPoint"));
|
||||||
vector refDirection(mirrorProperties.lookup("refDirection"));
|
vector refDirection(mirrorProperties.lookup("refDirection"));
|
||||||
|
|
||||||
word fieldName(mirrorProperties.lookup("fieldName"));
|
|
||||||
word dataBaseName(mirrorProperties.lookup("dataBaseName"));
|
word dataBaseName(mirrorProperties.lookup("dataBaseName"));
|
||||||
|
|
||||||
|
const wordList volScalarFieldNames(mirrorProperties.lookup("volScalarFields"));
|
||||||
|
const wordList volVectorFieldNames(mirrorProperties.lookup("volVectorFields"));
|
||||||
@ -66,16 +66,8 @@ int main(int argc, char *argv[])
|
|||||||
instantList timeDirs(recTime.times());
|
instantList timeDirs(recTime.times());
|
||||||
recTime.setTime(timeDirs[0],0);
|
recTime.setTime(timeDirs[0],0);
|
||||||
|
|
||||||
#include "readFields.H"
|
|
||||||
|
|
||||||
Info << fieldName << endl;
|
|
||||||
|
|
||||||
volScalarField transformedField = origField;
|
|
||||||
|
|
||||||
scalar t;
|
scalar t;
|
||||||
|
|
||||||
label shiftedTimeI = 0;
|
|
||||||
|
|
||||||
// check number of time directories
|
// check number of time directories
|
||||||
label shift = 0;
|
label shift = 0;
|
||||||
forAll(timeDirs, timeI)
|
forAll(timeDirs, timeI)
|
||||||
@ -95,14 +87,30 @@ int main(int argc, char *argv[])
|
|||||||
label cellI_transformed = -1;
|
label cellI_transformed = -1;
|
||||||
forAll(timeDirs, timeI)
|
forAll(timeDirs, timeI)
|
||||||
{
|
{
|
||||||
|
|
||||||
recTime.setTime(timeDirs[timeI], timeI);
|
recTime.setTime(timeDirs[timeI], timeI);
|
||||||
t = recTime.value();
|
t = recTime.value();
|
||||||
if(t < startTime) continue;
|
if(t < startTime) continue;
|
||||||
if(t > endTime) continue;
|
if(t > endTime) continue;
|
||||||
Info << "time = " << t << ", time index = " << timeI << endl;
|
Info << "time = " << t << ", time index = " << timeI << endl;
|
||||||
|
|
||||||
#include "readFields.H"
|
// volScalarFields
|
||||||
|
for (int sf = 0; sf < volScalarFieldNames.size(); sf++)
|
||||||
|
{
|
||||||
|
word fieldName = volScalarFieldNames[sf];
|
||||||
|
volScalarField origField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
fieldName,
|
||||||
|
recTime.timePath(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
volScalarField transformedField = origField;
|
||||||
|
|
||||||
forAll(transformedField, cellI)
|
forAll(transformedField, cellI)
|
||||||
{
|
{
|
||||||
@ -121,13 +129,54 @@ int main(int argc, char *argv[])
|
|||||||
transformedField[cellI] = transformedValue;
|
transformedField[cellI] = transformedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
shiftedTimeI = timeI + shift;
|
runTime.setTime(recTime.value() + origTimeRange + dt, timeI + shift);
|
||||||
t = recTime.value() + origTimeRange + dt;
|
Info << "creating transformed field " << fieldName << " for time = " << recTime.value() + origTimeRange + dt << endl;
|
||||||
runTime.setTime(t, shiftedTimeI);
|
|
||||||
Info << "creating transformed fields for time = " << t << ", time index = " << shiftedTimeI << endl;
|
|
||||||
transformedField.write();
|
transformedField.write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// volVectorFields
|
||||||
|
for (int vf = 0; vf < volVectorFieldNames.size(); vf++)
|
||||||
|
{
|
||||||
|
word fieldName = volVectorFieldNames[vf];
|
||||||
|
volVectorField origField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
fieldName,
|
||||||
|
recTime.timePath(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
volVectorField transformedField = origField;
|
||||||
|
|
||||||
|
forAll(transformedField, cellI)
|
||||||
|
{
|
||||||
|
vector position = mesh.C()[cellI];
|
||||||
|
vector transformedPosition = 2 * ((refPoint - position) & refDirection) * refDirection / (refDirection & refDirection) + position;
|
||||||
|
cellI_transformed = mesh.findCell(transformedPosition);
|
||||||
|
if(cellI_transformed < 0)
|
||||||
|
{
|
||||||
|
Info << "Couldn't find transformed cell. Stopping." << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector value = origField[cellI_transformed];
|
||||||
|
vector transformedValue = -2 * (value & refDirection) * refDirection / (refDirection & refDirection) + value;
|
||||||
|
|
||||||
|
transformedField[cellI] = transformedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
runTime.setTime(recTime.value() + origTimeRange + dt, timeI + shift);
|
||||||
|
Info << "creating transformed field " << fieldName << " for time = " << recTime.value() + origTimeRange + dt << endl;
|
||||||
|
transformedField.write();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Info << "\nEnd" << endl;
|
Info << "\nEnd" << endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1,3 +0,0 @@
|
|||||||
rBaseMirrorScalar.C
|
|
||||||
|
|
||||||
EXE=$(CFDEM_APP_DIR)/rBaseMirrorScalar
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
IOdictionary mirrorProperties
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"mirrorProperties",
|
|
||||||
mesh.time().constant(),
|
|
||||||
mesh,
|
|
||||||
IOobject::MUST_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
vector refPoint(mirrorProperties.lookup("refPoint"));
|
|
||||||
vector refDirection(mirrorProperties.lookup("refDirection"));
|
|
||||||
|
|
||||||
word fieldName(mirrorProperties.lookup("fieldName"));
|
|
||||||
word dataBaseName(mirrorProperties.lookup("dataBaseName"));
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
|
|
||||||
volScalarField origField
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
fieldName,
|
|
||||||
recTime.timePath(),
|
|
||||||
mesh,
|
|
||||||
IOobject::MUST_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
mesh
|
|
||||||
);
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
rBaseMirrorVec.C
|
|
||||||
|
|
||||||
EXE=$(CFDEM_APP_DIR)/rBaseMirrorVec
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
include $(CFDEM_ADD_LIBS_DIR)/additionalLibs
|
|
||||||
|
|
||||||
|
|
||||||
EXE_INC = \
|
|
||||||
$(PFLAGS) \
|
|
||||||
-I$(LIB_SRC)/finiteVolume/cfdTools \
|
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
|
||||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
|
||||||
-I$(LIB_SRC)/sampling/lnInclude \
|
|
||||||
-I$(LIB_SRC)/fvOptions/lnInclude \
|
|
||||||
-Wno-deprecated-copy
|
|
||||||
|
|
||||||
EXE_LIBS = \
|
|
||||||
-lfiniteVolume \
|
|
||||||
-lmeshTools \
|
|
||||||
-lsampling \
|
|
||||||
-lfvOptions
|
|
||||||
@ -1,134 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
|
|
||||||
\\/ 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 2 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, write to the Free Software Foundation,
|
|
||||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
Application
|
|
||||||
rBaseMirror
|
|
||||||
|
|
||||||
Description
|
|
||||||
Read time series and extend it by mirrored fields if geometry possesses
|
|
||||||
the same symmetry
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "fvCFD.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
// Main program:
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
argList::noParallel();
|
|
||||||
timeSelector::addOptions();
|
|
||||||
|
|
||||||
#include "setRootCase.H"
|
|
||||||
#include "createTime.H"
|
|
||||||
|
|
||||||
// read in start and end time from controlDict
|
|
||||||
|
|
||||||
scalar startTime=runTime.startTime().value();
|
|
||||||
scalar endTime=runTime.endTime().value();
|
|
||||||
scalar origTimeRange = endTime - startTime;
|
|
||||||
|
|
||||||
Info << "start time = " << runTime.startTime() << endl;
|
|
||||||
Info << "end time = " << runTime.endTime() << endl;
|
|
||||||
|
|
||||||
// check which time directories are present
|
|
||||||
//instantList timeDirs = timeSelector::select0(runTime, args);
|
|
||||||
//runTime.setTime(timeDirs[0], 0);
|
|
||||||
|
|
||||||
#include "createMesh.H"
|
|
||||||
|
|
||||||
#include "createFields.H"
|
|
||||||
|
|
||||||
Foam::Time recTime(fileName(dataBaseName), "", "../system", "../constant", false);
|
|
||||||
instantList timeDirs(recTime.times());
|
|
||||||
recTime.setTime(timeDirs[0],0);
|
|
||||||
|
|
||||||
#include "readFields.H"
|
|
||||||
|
|
||||||
Info << fieldName << endl;
|
|
||||||
|
|
||||||
volVectorField transformedField = origField;
|
|
||||||
|
|
||||||
scalar t;
|
|
||||||
|
|
||||||
label shiftedTimeI = 0;
|
|
||||||
|
|
||||||
// check number of time directories
|
|
||||||
label shift = 0;
|
|
||||||
forAll(timeDirs, timeI)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (recTime.timeName() == "constant") continue;
|
|
||||||
recTime.setTime(timeDirs[timeI], timeI);
|
|
||||||
t = recTime.value();
|
|
||||||
if(t < startTime) continue;
|
|
||||||
if(t > endTime) continue;
|
|
||||||
shift++;
|
|
||||||
}
|
|
||||||
|
|
||||||
scalar dt = origTimeRange / (shift - 1.0);
|
|
||||||
recTime.setEndTime(startTime + 2 * origTimeRange + dt);
|
|
||||||
|
|
||||||
label cellI_transformed = -1;
|
|
||||||
forAll(timeDirs, timeI)
|
|
||||||
{
|
|
||||||
recTime.setTime(timeDirs[timeI], timeI);
|
|
||||||
t = recTime.value();
|
|
||||||
if(t < startTime) continue;
|
|
||||||
if(t > endTime) continue;
|
|
||||||
Info << "time = " << t << ", time index = " << timeI << endl;
|
|
||||||
|
|
||||||
#include "readFields.H"
|
|
||||||
|
|
||||||
forAll(transformedField, cellI)
|
|
||||||
{
|
|
||||||
vector position = mesh.C()[cellI];
|
|
||||||
vector transformedPosition = 2 * ((refPoint - position) & refDirection) * refDirection / (refDirection & refDirection) + position;
|
|
||||||
cellI_transformed = mesh.findCell(transformedPosition);
|
|
||||||
if(cellI_transformed < 0)
|
|
||||||
{
|
|
||||||
Info << "Couldn't find transformed cell. Stopping." << endl;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector value = origField[cellI_transformed];
|
|
||||||
vector transformedValue = -2 * (value & refDirection) * refDirection / (refDirection & refDirection) + value;
|
|
||||||
|
|
||||||
transformedField[cellI] = transformedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
shiftedTimeI = timeI + shift;
|
|
||||||
t = recTime.value() + origTimeRange + dt;
|
|
||||||
runTime.setTime(t, shiftedTimeI);
|
|
||||||
Info << "creating transformed fields for time = " << t << ", time index = " << shiftedTimeI << endl;
|
|
||||||
transformedField.write();
|
|
||||||
}
|
|
||||||
|
|
||||||
Info << "\nEnd" << endl;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
|
|
||||||
volVectorField origField
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
fieldName,
|
|
||||||
recTime.timePath(),
|
|
||||||
mesh,
|
|
||||||
IOobject::MUST_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
mesh
|
|
||||||
);
|
|
||||||
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
rcfdemSolverRhoSteadyPimple/dir
|
rcfdemSolverRhoSteadyPimple/dir
|
||||||
rcfdemSolverCoupledHeattransfer/dir
|
rcfdemSolverCoupledHeattransfer/dir
|
||||||
|
rcfdemSolverForcedTracers/dir
|
||||||
rStatAnalysis/dir
|
rStatAnalysis/dir
|
||||||
rcfdemSolverBase/dir
|
rcfdemSolverBase/dir
|
||||||
rtfmSolverSpecies/dir
|
rtfmSolverSpecies/dir
|
||||||
@ -10,3 +11,6 @@ cfdemSolverIB/dir
|
|||||||
cfdemSolverPisoScalar/dir
|
cfdemSolverPisoScalar/dir
|
||||||
cfdemSolverRhoPimpleChem/dir
|
cfdemSolverRhoPimpleChem/dir
|
||||||
cfdemSolverMultiphase/dir
|
cfdemSolverMultiphase/dir
|
||||||
|
rcfdemSolverRhoSteadyPimpleChem/dir
|
||||||
|
rctfSpeciesTransport/dir
|
||||||
|
cfdemSolverPisoFreeStreaming/dir
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
|
displacementField/dir
|
||||||
cfdemPostproc/dir
|
cfdemPostproc/dir
|
||||||
rSmoother/dir
|
rSmoother/dir
|
||||||
rBaseMirror/rBaseMirrorScalar/dir
|
rBaseMirror/rBaseMirror/dir
|
||||||
rBaseMirror/rBaseMirrorVec/dir
|
|
||||||
|
|||||||
@ -37,12 +37,13 @@ $(chemistryModels)/noChemistry/noChemistry.C
|
|||||||
$(chemistryModels)/diffusionCoefficients/diffusionCoefficients.C
|
$(chemistryModels)/diffusionCoefficients/diffusionCoefficients.C
|
||||||
$(chemistryModels)/massTransferCoeff/massTransferCoeff.C
|
$(chemistryModels)/massTransferCoeff/massTransferCoeff.C
|
||||||
$(chemistryModels)/reactantPerParticle/reactantPerParticle.C
|
$(chemistryModels)/reactantPerParticle/reactantPerParticle.C
|
||||||
|
$(chemistryModels)/initMultiLayers/initMultiLayers.C
|
||||||
|
|
||||||
$(energyModels)/energyModel/energyModel.C
|
$(energyModels)/energyModel/energyModel.C
|
||||||
$(energyModels)/energyModel/newEnergyModel.C
|
$(energyModels)/energyModel/newEnergyModel.C
|
||||||
$(energyModels)/heatTransferGunn/heatTransferGunn.C
|
$(energyModels)/heatTransferGunn/heatTransferGunn.C
|
||||||
$(energyModels)/heatTransferRanzMarshall/heatTransferRanzMarshall.C
|
$(energyModels)/heatTransferRanzMarshall/heatTransferRanzMarshall.C
|
||||||
$(energyModels)/heatTransferGranConduction/heatTransferGranConduction.C
|
$(energyModels)/heatTransferInterGrain/heatTransferInterGrain.C
|
||||||
$(energyModels)/reactionHeat/reactionHeat.C
|
$(energyModels)/reactionHeat/reactionHeat.C
|
||||||
|
|
||||||
$(thermCondModels)/thermCondModel/thermCondModel.C
|
$(thermCondModels)/thermCondModel/thermCondModel.C
|
||||||
@ -92,6 +93,8 @@ $(forceModels)/surfaceTensionForce/surfaceTensionForce.C
|
|||||||
$(forceModels)/gradPForceSmooth/gradPForceSmooth.C
|
$(forceModels)/gradPForceSmooth/gradPForceSmooth.C
|
||||||
$(forceModels)/particleDeformation/particleDeformation.C
|
$(forceModels)/particleDeformation/particleDeformation.C
|
||||||
$(forceModels)/turbulentDispersion/turbulentDispersion.C
|
$(forceModels)/turbulentDispersion/turbulentDispersion.C
|
||||||
|
$(forceModels)/terminalVelocity/terminalVelocity.C
|
||||||
|
$(forceModels)/turbulentVelocityFluctuations/turbulentVelocityFluctuations.C
|
||||||
|
|
||||||
$(forceModelsMS)/forceModelMS/forceModelMS.C
|
$(forceModelsMS)/forceModelMS/forceModelMS.C
|
||||||
$(forceModelsMS)/forceModelMS/newForceModelMS.C
|
$(forceModelsMS)/forceModelMS/newForceModelMS.C
|
||||||
@ -108,6 +111,7 @@ $(otherForceModels)/otherForceModel/newOtherForceModel.C
|
|||||||
$(otherForceModels)/gravity/gravity.C
|
$(otherForceModels)/gravity/gravity.C
|
||||||
$(otherForceModels)/weightSecondaryPhase/weightSecondaryPhase.C
|
$(otherForceModels)/weightSecondaryPhase/weightSecondaryPhase.C
|
||||||
$(otherForceModels)/expParticleForces/expParticleForces.C
|
$(otherForceModels)/expParticleForces/expParticleForces.C
|
||||||
|
$(otherForceModels)/secondaryPhaseInducedBuoyancy/secondaryPhaseInducedBuoyancy.C
|
||||||
|
|
||||||
$(probeModels)/probeModel/probeModel.C
|
$(probeModels)/probeModel/probeModel.C
|
||||||
$(probeModels)/probeModel/newProbeModel.C
|
$(probeModels)/probeModel/newProbeModel.C
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
|
// check model type
|
||||||
|
// referring to: Zhou et al. 2010,JFM
|
||||||
|
|
||||||
// check model type
|
word modelType = particleCloud.modelType();
|
||||||
// referring to: Zhou et al. 2010,JFM
|
|
||||||
word modelType = particleCloud.modelType();
|
|
||||||
|
|
||||||
|
if (particleCloud.modelCheck())
|
||||||
|
{
|
||||||
//Warning << "model type not being checked" << endl;
|
//Warning << "model type not being checked" << endl;
|
||||||
if (modelType=="Bfull"){
|
if (modelType=="Bfull"){
|
||||||
Info << "solving volume averaged Navier Stokes equations of type B\n"<< endl;
|
Info << "solving volume averaged Navier Stokes equations of type B\n"<< endl;
|
||||||
@ -102,3 +104,8 @@
|
|||||||
|
|
||||||
if (particleCloud.smoothingM().type() == "temporalSmoothing")
|
if (particleCloud.smoothingM().type() == "temporalSmoothing")
|
||||||
FatalError << "the temporalSmoothing model does not support smoothing of the exchange fields, please see documentation!" << endl;
|
FatalError << "the temporalSmoothing model does not support smoothing of the exchange fields, please see documentation!" << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Warning << "Model check deactivated." << endl;
|
||||||
|
}
|
||||||
|
|||||||
@ -83,11 +83,14 @@ cfdemCloud::cfdemCloud
|
|||||||
verbose_(couplingProperties_.found("verbose")),
|
verbose_(couplingProperties_.found("verbose")),
|
||||||
ignore_(couplingProperties_.found("ignore")),
|
ignore_(couplingProperties_.found("ignore")),
|
||||||
allowCFDsubTimestep_(true),
|
allowCFDsubTimestep_(true),
|
||||||
|
modelCheck_(couplingProperties_.lookupOrDefault<bool>("modelCheck",true)),
|
||||||
limitDEMForces_(couplingProperties_.found("limitDEMForces")),
|
limitDEMForces_(couplingProperties_.found("limitDEMForces")),
|
||||||
phaseInForces_(couplingProperties_.found("phaseInForcesTime")),
|
phaseInForces_(couplingProperties_.found("phaseInForcesTime")),
|
||||||
getParticleDensities_(couplingProperties_.lookupOrDefault<bool>("getParticleDensities",false)),
|
getParticleDensities_(couplingProperties_.lookupOrDefault<bool>("getParticleDensities",false)),
|
||||||
getParticleEffVolFactors_(couplingProperties_.lookupOrDefault<bool>("getParticleEffVolFactors",false)),
|
getParticleEffVolFactors_(couplingProperties_.lookupOrDefault<bool>("getParticleEffVolFactors",false)),
|
||||||
getParticleTypes_(couplingProperties_.lookupOrDefault<bool>("getParticleTypes",false)),
|
getParticleTypes_(couplingProperties_.lookupOrDefault<bool>("getParticleTypes",false)),
|
||||||
|
streamingMode_(couplingProperties_.lookupOrDefault<bool>("streamingMode",false)),
|
||||||
|
streamingFluc_(couplingProperties_.lookupOrDefault<bool>("streamingFluc",false)),
|
||||||
maxDEMForce_(0.),
|
maxDEMForce_(0.),
|
||||||
phaseInForcesTime_(couplingProperties_.lookupOrDefault<scalar>("phaseInForcesTime",0.0)),
|
phaseInForcesTime_(couplingProperties_.lookupOrDefault<scalar>("phaseInForcesTime",0.0)),
|
||||||
modelType_(couplingProperties_.lookup("modelType")),
|
modelType_(couplingProperties_.lookup("modelType")),
|
||||||
@ -438,17 +441,28 @@ void cfdemCloud::getDEMdata()
|
|||||||
|
|
||||||
void cfdemCloud::giveDEMdata()
|
void cfdemCloud::giveDEMdata()
|
||||||
{
|
{
|
||||||
if(forceM(0).coupleForce())
|
if (forceM(0).coupleForce())
|
||||||
|
{
|
||||||
|
if (!streamingMode_)
|
||||||
{
|
{
|
||||||
dataExchangeM().giveData("dragforce","vector-atom",DEMForces_);
|
dataExchangeM().giveData("dragforce","vector-atom",DEMForces_);
|
||||||
|
|
||||||
if(impDEMdrag_)
|
if (impDEMdrag_)
|
||||||
{
|
{
|
||||||
if(verbose_) Info << "sending Ksl and uf" << endl;
|
if (verbose_) Info << "sending Ksl and uf" << endl;
|
||||||
dataExchangeM().giveData("Ksl","scalar-atom",Cds_);
|
dataExchangeM().giveData("Ksl","scalar-atom",Cds_);
|
||||||
dataExchangeM().giveData("uf","vector-atom",fluidVel_);
|
dataExchangeM().giveData("uf","vector-atom",fluidVel_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataExchangeM().giveData("vrec","vector-atom",particleConvVel_);
|
||||||
|
if (streamingFluc_)
|
||||||
|
{
|
||||||
|
dataExchangeM().giveData("vfluc","vector-atom",particleFlucVel_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if(verbose_) Info << "giveDEMdata done." << endl;
|
if(verbose_) Info << "giveDEMdata done." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -95,6 +95,8 @@ protected:
|
|||||||
|
|
||||||
bool allowCFDsubTimestep_;
|
bool allowCFDsubTimestep_;
|
||||||
|
|
||||||
|
const bool modelCheck_;
|
||||||
|
|
||||||
const bool limitDEMForces_;
|
const bool limitDEMForces_;
|
||||||
|
|
||||||
const bool phaseInForces_;
|
const bool phaseInForces_;
|
||||||
@ -105,6 +107,10 @@ protected:
|
|||||||
|
|
||||||
const bool getParticleTypes_;
|
const bool getParticleTypes_;
|
||||||
|
|
||||||
|
const bool streamingMode_;
|
||||||
|
|
||||||
|
const bool streamingFluc_;
|
||||||
|
|
||||||
scalar maxDEMForce_;
|
scalar maxDEMForce_;
|
||||||
|
|
||||||
scalar phaseInForcesTime_;
|
scalar phaseInForcesTime_;
|
||||||
@ -291,6 +297,8 @@ public:
|
|||||||
|
|
||||||
label liggghtsCommandModelIndex(const word&) const;
|
label liggghtsCommandModelIndex(const word&) const;
|
||||||
|
|
||||||
|
inline void scaleForce(int, scalar);
|
||||||
|
|
||||||
inline void setCG(double);
|
inline void setCG(double);
|
||||||
|
|
||||||
inline scalar cg() const;
|
inline scalar cg() const;
|
||||||
@ -305,6 +313,8 @@ public:
|
|||||||
|
|
||||||
inline bool ignore() const;
|
inline bool ignore() const;
|
||||||
|
|
||||||
|
inline bool modelCheck() const;
|
||||||
|
|
||||||
inline const fvMesh& mesh() const;
|
inline const fvMesh& mesh() const;
|
||||||
|
|
||||||
inline bool solveFlow() const;
|
inline bool solveFlow() const;
|
||||||
|
|||||||
@ -89,6 +89,15 @@ inline bool cfdemCloud::treatVoidCellsAsExplicitForce() const
|
|||||||
return treatVoidCellsAsExplicitForce_;
|
return treatVoidCellsAsExplicitForce_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void cfdemCloud::scaleForce(int index, scalar factor)
|
||||||
|
{
|
||||||
|
for (int i=0; i<3; ++i)
|
||||||
|
{
|
||||||
|
expForces_[index][i] *= factor;
|
||||||
|
impForces_[index][i] *= factor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline scalar cfdemCloud::cg() const
|
inline scalar cfdemCloud::cg() const
|
||||||
{
|
{
|
||||||
return cg_;
|
return cg_;
|
||||||
@ -99,6 +108,11 @@ inline bool cfdemCloud::ignore() const
|
|||||||
return ignore_;
|
return ignore_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool cfdemCloud::modelCheck() const
|
||||||
|
{
|
||||||
|
return modelCheck_;
|
||||||
|
}
|
||||||
|
|
||||||
inline const fvMesh& cfdemCloud::mesh() const
|
inline const fvMesh& cfdemCloud::mesh() const
|
||||||
{
|
{
|
||||||
return mesh_;
|
return mesh_;
|
||||||
|
|||||||
@ -0,0 +1,306 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
License
|
||||||
|
|
||||||
|
This 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.
|
||||||
|
|
||||||
|
This code 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 this code. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "error.H"
|
||||||
|
#include "initMultiLayers.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "dataExchangeModel.H"
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(initMultiLayers, 0);
|
||||||
|
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
chemistryModel,
|
||||||
|
initMultiLayers,
|
||||||
|
dictionary
|
||||||
|
);
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Construct from components
|
||||||
|
initMultiLayers::initMultiLayers
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
cfdemCloudEnergy& sm
|
||||||
|
)
|
||||||
|
:
|
||||||
|
chemistryModel(dict,sm),
|
||||||
|
propsDict_(dict.subDict(typeName + "Props")),
|
||||||
|
interpolation_(propsDict_.lookupOrDefault<bool>("interpolation",false)),
|
||||||
|
mesh_(sm.mesh()),
|
||||||
|
verbose_(propsDict_.lookupOrDefault<bool>("verbose",false)),
|
||||||
|
maxNumLayers_(0),
|
||||||
|
numLayers_(propsDict_.lookupOrDefault<labelList>("numLayers",labelList(1,-1))),
|
||||||
|
partTypes_(propsDict_.lookupOrDefault<labelList>("partTypes",labelList(1,-1))),
|
||||||
|
relRadiiRegName_(typeName + "relRadii"),
|
||||||
|
filepath_(string(propsDict_.lookup("filepath"))),
|
||||||
|
initialized_(false)
|
||||||
|
{
|
||||||
|
for (label i=0; i<numLayers_.size(); i++)
|
||||||
|
{
|
||||||
|
if (numLayers_[i] > maxNumLayers_) maxNumLayers_=numLayers_[i];
|
||||||
|
}
|
||||||
|
if (maxNumLayers_ > 4)
|
||||||
|
{
|
||||||
|
FatalError<< "Currently, not more than four layers are supported." << abort(FatalError);
|
||||||
|
}
|
||||||
|
defaultRelRadii_ = vector(0.998, 0.995, 0.98);
|
||||||
|
particleCloud_.checkCG(false);
|
||||||
|
particleCloud_.registerParticleProperty<double**>(relRadiiRegName_,maxNumLayers_);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
initMultiLayers::~initMultiLayers()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool initMultiLayers::init()
|
||||||
|
{
|
||||||
|
double**& relRadii = particleCloud_.getParticlePropertyRef<double**>(relRadiiRegName_);
|
||||||
|
// for all types of particles
|
||||||
|
for(label types=0; types<partTypes_.size(); types++)
|
||||||
|
{
|
||||||
|
label type = partTypes_[types];
|
||||||
|
|
||||||
|
labelList indices;
|
||||||
|
vectorList positions, relradii;
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << filepath_ << type;
|
||||||
|
std::string filename = ss.str();
|
||||||
|
|
||||||
|
if (access( filename.c_str(), F_OK ) == -1)
|
||||||
|
{
|
||||||
|
Info << "initMultiLayers: Data file " << filename << "not found. No initialisation of layer radii possible." << endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Info << "\nReading" << endl;
|
||||||
|
Info << "\t" << filename << endl;
|
||||||
|
readDump(filename, type, indices, positions, relradii);
|
||||||
|
|
||||||
|
Info << "Binning particle displacements on mesh for type " << type << endl;
|
||||||
|
|
||||||
|
volScalarField particlesInCell
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"particlesInCell",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensionedScalar("zero", dimensionSet(0,0,0,0,0), 0.0)
|
||||||
|
);
|
||||||
|
|
||||||
|
vector position, relrad;
|
||||||
|
ss.str("");
|
||||||
|
ss << "relRadiiField" << type;
|
||||||
|
std::string fieldname = ss.str();
|
||||||
|
volVectorField relRadiiField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
fieldname,
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensionedVector("zero", dimensionSet(0,0,0,0,0), vector::zero)
|
||||||
|
);
|
||||||
|
|
||||||
|
label cellI = -1;
|
||||||
|
for (label lineI = 0; lineI < indices.size(); lineI++)
|
||||||
|
{
|
||||||
|
position = positions[lineI];
|
||||||
|
relrad = relradii[lineI];
|
||||||
|
cellI = mesh_.findCell(position);
|
||||||
|
if (cellI < 0) continue;
|
||||||
|
particlesInCell[cellI] += 1;
|
||||||
|
relRadiiField[cellI] += relrad;
|
||||||
|
}
|
||||||
|
|
||||||
|
forAll (mesh_.C(), cellJ)
|
||||||
|
{
|
||||||
|
if (particlesInCell[cellJ] > 0.5)
|
||||||
|
{
|
||||||
|
relRadiiField[cellJ] /= particlesInCell[cellJ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill field
|
||||||
|
|
||||||
|
|
||||||
|
// fill particle arrays
|
||||||
|
label cellK = -1;
|
||||||
|
label cellKoccupied = -1;
|
||||||
|
label partType = -1;
|
||||||
|
label listIndex = -1;
|
||||||
|
vector relRadiiLoopVar = vector::zero;
|
||||||
|
for(int index = 0;index < particleCloud_.numberOfParticles(); ++index)
|
||||||
|
{
|
||||||
|
cellK = particleCloud_.cellIDs()[index][0];
|
||||||
|
partType = particleCloud_.particleType(index);
|
||||||
|
if(cellK >= 0 && partType == type)
|
||||||
|
{
|
||||||
|
// look for the nearest occupied cell
|
||||||
|
cellKoccupied = findNearestCellWithValue(cellK, particlesInCell);
|
||||||
|
listIndex = getListIndex(partType);
|
||||||
|
if (cellKoccupied >= 0)
|
||||||
|
{
|
||||||
|
relRadiiLoopVar = relRadiiField[cellKoccupied];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
relRadiiLoopVar = defaultRelRadii_;
|
||||||
|
}
|
||||||
|
relRadii[index][0] = 1.0;
|
||||||
|
for (label i=1;i<numLayers_[listIndex];i++)
|
||||||
|
{
|
||||||
|
relRadii[index][i] = relRadiiLoopVar.component(i-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (verbose_) relRadiiField.write();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void initMultiLayers::execute()
|
||||||
|
{
|
||||||
|
if(!initialized_)
|
||||||
|
{
|
||||||
|
if (init())
|
||||||
|
{
|
||||||
|
double**& relRadii = particleCloud_.getParticlePropertyRef<double**>(relRadiiRegName_);
|
||||||
|
particleCloud_.dataExchangeM().giveData("relRadii","vector-atom", relRadii);
|
||||||
|
}
|
||||||
|
initialized_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label initMultiLayers::findNearestCellWithValue(label refCell, volScalarField &particlesInCell) const
|
||||||
|
{
|
||||||
|
if (particlesInCell[refCell] > 0.5) return refCell;
|
||||||
|
|
||||||
|
std::set<label> neighbors;
|
||||||
|
std::set<label> newNeighbors;
|
||||||
|
std::set<label> recentNeighbors;
|
||||||
|
|
||||||
|
neighbors.insert(refCell);
|
||||||
|
recentNeighbors.insert(refCell);
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
for (std::set<label>::iterator it=recentNeighbors.begin(); it!=recentNeighbors.end(); ++it)
|
||||||
|
{
|
||||||
|
labelList adjacent = mesh_.cellCells()[*it];
|
||||||
|
label adj;
|
||||||
|
for (label j=0; j<adjacent.size(); j++)
|
||||||
|
{
|
||||||
|
adj = adjacent[j];
|
||||||
|
std::set<label>::iterator it2 = neighbors.find(adj);
|
||||||
|
if (it2 == neighbors.end())
|
||||||
|
{
|
||||||
|
newNeighbors.insert(adj);
|
||||||
|
neighbors.insert(adj);
|
||||||
|
if (particlesInCell[adj] > 0.5) return adj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if all cells have been searched and none was occupied, return -1; assumes that reasonable default value is available
|
||||||
|
if (newNeighbors.size() == 0) return -1;
|
||||||
|
recentNeighbors.clear();
|
||||||
|
recentNeighbors = newNeighbors;
|
||||||
|
newNeighbors.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label initMultiLayers::getListIndex(label testElement) const
|
||||||
|
{
|
||||||
|
for(label ind = 0; ind<partTypes_.size(); ind++)
|
||||||
|
{
|
||||||
|
if (partTypes_[ind] == testElement) return ind;
|
||||||
|
}
|
||||||
|
// testing
|
||||||
|
Pout << "Cannot find list index for element " << testElement << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initMultiLayers::readDump(std::string filename, label type, labelList &indices, vectorList &positions, vectorList &relradii)
|
||||||
|
{
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
const label leadingLines = 9;
|
||||||
|
label lineCounter = 0;
|
||||||
|
label partIndex, partType;
|
||||||
|
scalar x, y, z;
|
||||||
|
scalar r0 = 1.0;
|
||||||
|
scalar r1 = 1.0;
|
||||||
|
scalar r2 = 1.0;
|
||||||
|
scalar r3 = 1.0;
|
||||||
|
|
||||||
|
indices.clear();
|
||||||
|
positions.clear();
|
||||||
|
relradii.clear();
|
||||||
|
|
||||||
|
std::ifstream file(filename);
|
||||||
|
std::string str;
|
||||||
|
while (std::getline(file, str))
|
||||||
|
{
|
||||||
|
if (lineCounter >= leadingLines)
|
||||||
|
{
|
||||||
|
sscanf(str.c_str(), "%d %d %lf %lf %lf %lf %lf %lf %lf", &partIndex, &partType, &x, &y, &z, &r0, &r1, &r2, &r3);
|
||||||
|
if (partType != type)
|
||||||
|
{
|
||||||
|
FatalError<< "Particle of type " << partType << " detected in " << filename << abort(FatalError);
|
||||||
|
}
|
||||||
|
indices.append(partIndex);
|
||||||
|
positions.append(vector(x,y,z));
|
||||||
|
relradii.append(vector(r1,r2,r3));
|
||||||
|
}
|
||||||
|
lineCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
License
|
||||||
|
|
||||||
|
This 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.
|
||||||
|
|
||||||
|
This code 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 this code. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria
|
||||||
|
|
||||||
|
Description
|
||||||
|
Model to initiate multilayer radii from dump files
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef initMultiLayers_H
|
||||||
|
#define initMultiLayers_H
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "fvCFD.H"
|
||||||
|
#include "cfdemCloudEnergy.H"
|
||||||
|
#include "chemistryModel.H"
|
||||||
|
#include "vectorList.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class species Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// for future use:
|
||||||
|
// + communicate every N steps
|
||||||
|
|
||||||
|
class initMultiLayers
|
||||||
|
:
|
||||||
|
public chemistryModel
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
dictionary propsDict_;
|
||||||
|
|
||||||
|
bool interpolation_;
|
||||||
|
|
||||||
|
const fvMesh& mesh_;
|
||||||
|
|
||||||
|
bool verbose_;
|
||||||
|
|
||||||
|
label maxNumLayers_;
|
||||||
|
|
||||||
|
labelList numLayers_;
|
||||||
|
|
||||||
|
labelList partTypes_;
|
||||||
|
|
||||||
|
vector defaultRelRadii_;
|
||||||
|
|
||||||
|
const word relRadiiRegName_;
|
||||||
|
|
||||||
|
std::string filepath_;
|
||||||
|
|
||||||
|
bool initialized_;
|
||||||
|
|
||||||
|
bool init();
|
||||||
|
|
||||||
|
void readDump(std::string, label, labelList &, vectorList &, vectorList &);
|
||||||
|
|
||||||
|
label findNearestCellWithValue(label, volScalarField &) const;
|
||||||
|
|
||||||
|
label getListIndex(label) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("initMultiLayers");
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
initMultiLayers
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
cfdemCloudEnergy& sm
|
||||||
|
);
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
|
||||||
|
virtual ~initMultiLayers();
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
void execute();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -98,11 +98,17 @@ species::species
|
|||||||
partMolarConcName_(propsDict_.lookupOrDefault<word>("partMoleName","partMolarConc")),
|
partMolarConcName_(propsDict_.lookupOrDefault<word>("partMoleName","partMolarConc")),
|
||||||
loopCounter_(-1),
|
loopCounter_(-1),
|
||||||
Nevery_(propsDict_.lookupOrDefault<label>("Nevery",1)),
|
Nevery_(propsDict_.lookupOrDefault<label>("Nevery",1)),
|
||||||
|
couplingTimestep_(0.0),
|
||||||
massSourceCurr_(0.0),
|
massSourceCurr_(0.0),
|
||||||
massSourceTot_(0.0),
|
massSourceTot_(0.0),
|
||||||
initialized_(false)
|
initialized_(false)
|
||||||
{
|
{
|
||||||
particleCloud_.checkCG(false);
|
particleCloud_.checkCG(false);
|
||||||
|
|
||||||
|
scalar dtDEM = particleCloud_.dataExchangeM().DEMts();
|
||||||
|
scalar dtCFD = mesh_.time().deltaTValue();
|
||||||
|
couplingTimestep_ = max(dtDEM,dtCFD);
|
||||||
|
|
||||||
particleCloud_.registerParticleProperty<double**>(partTempName_,1);
|
particleCloud_.registerParticleProperty<double**>(partTempName_,1);
|
||||||
particleCloud_.registerParticleProperty<double**>(partRhoName_,1);
|
particleCloud_.registerParticleProperty<double**>(partRhoName_,1);
|
||||||
particleCloud_.registerParticleProperty<double**>(partMolarConcName_,1);
|
particleCloud_.registerParticleProperty<double**>(partMolarConcName_,1);
|
||||||
@ -268,7 +274,6 @@ void species::execute()
|
|||||||
|
|
||||||
// pull changeOfSpeciesMass_, transform onto fields changeOfSpeciesMassFields_, add them up on changeOfGasMassField_
|
// pull changeOfSpeciesMass_, transform onto fields changeOfSpeciesMassFields_, add them up on changeOfGasMassField_
|
||||||
{
|
{
|
||||||
scalar timestep = mesh_.time().deltaTValue();
|
|
||||||
changeOfGasMassField_.primitiveFieldRef() = 0.0;
|
changeOfGasMassField_.primitiveFieldRef() = 0.0;
|
||||||
changeOfGasMassField_.boundaryFieldRef() = 0.0;
|
changeOfGasMassField_.boundaryFieldRef() = 0.0;
|
||||||
for (int i=0; i<speciesNames_.size();i++)
|
for (int i=0; i<speciesNames_.size();i++)
|
||||||
@ -291,17 +296,17 @@ void species::execute()
|
|||||||
|
|
||||||
// take care for implementation in LIGGGHTS: species produced from particles defined positive
|
// take care for implementation in LIGGGHTS: species produced from particles defined positive
|
||||||
// changeOf...Fields need to be mass per volume per timestep
|
// changeOf...Fields need to be mass per volume per timestep
|
||||||
changeOfSpeciesMassFields_[i].primitiveFieldRef() /= (changeOfSpeciesMassFields_[i].mesh().V() * Nevery_ * timestep);
|
changeOfSpeciesMassFields_[i].primitiveFieldRef() /= (changeOfSpeciesMassFields_[i].mesh().V() * Nevery_ * couplingTimestep_);
|
||||||
changeOfSpeciesMassFields_[i].correctBoundaryConditions();
|
changeOfSpeciesMassFields_[i].correctBoundaryConditions();
|
||||||
changeOfGasMassField_ += changeOfSpeciesMassFields_[i];
|
changeOfGasMassField_ += changeOfSpeciesMassFields_[i];
|
||||||
|
|
||||||
if (verbose_)
|
if (verbose_)
|
||||||
{
|
{
|
||||||
Info << "total conversion of species" << speciesNames_[i] << " = "
|
Info << "total conversion of species" << speciesNames_[i] << " = "
|
||||||
<< gSum(changeOfSpeciesMassFields_[i]*1.0*changeOfSpeciesMassFields_[i].mesh().V() * Nevery_ * timestep) << endl;
|
<< gSum(changeOfSpeciesMassFields_[i]*1.0*changeOfSpeciesMassFields_[i].mesh().V() * Nevery_ * couplingTimestep_) << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
massSourceCurr_ = gSum(changeOfGasMassField_*1.0*changeOfGasMassField_.mesh().V() * Nevery_ * timestep);
|
massSourceCurr_ = gSum(changeOfGasMassField_*1.0*changeOfGasMassField_.mesh().V() * Nevery_ * couplingTimestep_);
|
||||||
massSourceTot_ += massSourceCurr_;
|
massSourceTot_ += massSourceCurr_;
|
||||||
|
|
||||||
if (verbose_)
|
if (verbose_)
|
||||||
|
|||||||
@ -99,6 +99,8 @@ private:
|
|||||||
|
|
||||||
label Nevery_;
|
label Nevery_;
|
||||||
|
|
||||||
|
scalar couplingTimestep_;
|
||||||
|
|
||||||
scalar massSourceCurr_;
|
scalar massSourceCurr_;
|
||||||
|
|
||||||
scalar massSourceTot_;
|
scalar massSourceTot_;
|
||||||
|
|||||||
@ -1,249 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
License
|
|
||||||
|
|
||||||
This 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.
|
|
||||||
|
|
||||||
This code 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 this code. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "error.H"
|
|
||||||
#include "heatTransferGranConduction.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(heatTransferGranConduction, 0);
|
|
||||||
|
|
||||||
addToRunTimeSelectionTable(energyModel, heatTransferGranConduction, dictionary);
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
// Construct from components
|
|
||||||
heatTransferGranConduction::heatTransferGranConduction
|
|
||||||
(
|
|
||||||
const dictionary& dict,
|
|
||||||
cfdemCloudEnergy& sm
|
|
||||||
)
|
|
||||||
:
|
|
||||||
energyModel(dict,sm),
|
|
||||||
propsDict_(dict.subDict(typeName + "Props")),
|
|
||||||
multiTypes_(false),
|
|
||||||
verbose_(propsDict_.lookupOrDefault<bool>("verbose",false)),
|
|
||||||
calcTotalHeatFlux_(propsDict_.lookupOrDefault<bool>("calcTotalHeatFlux",false)),
|
|
||||||
totalHeatFlux_(0.0),
|
|
||||||
QPartPartName_(propsDict_.lookupOrDefault<word>("QPartPartName","QPartPart")),
|
|
||||||
QPartPart_
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
QPartPartName_,
|
|
||||||
sm.mesh().time().timeName(),
|
|
||||||
sm.mesh(),
|
|
||||||
IOobject::READ_IF_PRESENT,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
sm.mesh(),
|
|
||||||
dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0)
|
|
||||||
),
|
|
||||||
partEffThermCondField_
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"partEffThermCondField",
|
|
||||||
sm.mesh().time().timeName(),
|
|
||||||
sm.mesh(),
|
|
||||||
IOobject::READ_IF_PRESENT,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
sm.mesh(),
|
|
||||||
dimensionedScalar("one", dimensionSet(1, 1, -3, -1,0,0,0), 1.0),
|
|
||||||
"zeroGradient"
|
|
||||||
),
|
|
||||||
partThermCondField_
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"partThermCondField",
|
|
||||||
sm.mesh().time().timeName(),
|
|
||||||
sm.mesh(),
|
|
||||||
IOobject::READ_IF_PRESENT,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
sm.mesh(),
|
|
||||||
dimensionedScalar("one", dimensionSet(1, 1, -3, -1,0,0,0), 1.0),
|
|
||||||
"zeroGradient"
|
|
||||||
),
|
|
||||||
partTempField_(sm.mesh().lookupObject<volScalarField>("partTemp")),
|
|
||||||
prescribedVoidfractionFieldName_(propsDict_.lookupOrDefault<word>("prescribedVoidfractionFieldName","voidfraction")),
|
|
||||||
prescribedVoidfraction_(sm.mesh().lookupObject<volScalarField> (prescribedVoidfractionFieldName_)),
|
|
||||||
voidfractionFieldName_(propsDict_.lookupOrDefault<word>("voidfractionFieldName","voidfraction")),
|
|
||||||
voidfraction_(sm.mesh().lookupObject<volScalarField> (voidfractionFieldName_)),
|
|
||||||
partHeatFluxName_(propsDict_.lookupOrDefault<word>("partHeatFluxName","conductiveHeatFlux")),
|
|
||||||
typePartThermCond_(propsDict_.lookupOrDefault<scalarList>("thermalConductivities",scalarList(1,-1.0))),
|
|
||||||
partThermCondRegName_(typeName + "partThermCond")
|
|
||||||
{
|
|
||||||
particleCloud_.registerParticleProperty<double**>(partHeatFluxName_,1);
|
|
||||||
particleCloud_.registerParticleProperty<double**>(partThermCondRegName_,1);
|
|
||||||
|
|
||||||
if (typePartThermCond_[0] < 0.0)
|
|
||||||
{
|
|
||||||
FatalError << "heatTransferGranConduction: provide list of thermal conductivities." << abort(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typePartThermCond_.size() > 1)
|
|
||||||
{
|
|
||||||
multiTypes_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (multiTypes_ && !particleCloud_.getParticleTypes())
|
|
||||||
{
|
|
||||||
FatalError << "heatTransferGranConduction needs data for more than one type, but types are not communicated." << abort(FatalError);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verbose_)
|
|
||||||
{
|
|
||||||
QPartPart_.writeOpt() = IOobject::AUTO_WRITE;
|
|
||||||
QPartPart_.write();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
heatTransferGranConduction::~heatTransferGranConduction()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * //
|
|
||||||
// * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void heatTransferGranConduction::calcEnergyContribution()
|
|
||||||
{
|
|
||||||
calcPartEffThermCond();
|
|
||||||
|
|
||||||
QPartPart_ = fvc::laplacian(partEffThermCondField_,partTempField_);
|
|
||||||
|
|
||||||
label cellI=0;
|
|
||||||
scalar partVolume(0);
|
|
||||||
scalar QPartPart(0);
|
|
||||||
scalar voidfraction(1);
|
|
||||||
|
|
||||||
totalHeatFlux_ = 0.0;
|
|
||||||
double**& partHeatFlux_ = particleCloud_.getParticlePropertyRef<double**>(partHeatFluxName_);
|
|
||||||
|
|
||||||
for(int index = 0;index < particleCloud_.numberOfParticles(); ++index)
|
|
||||||
{
|
|
||||||
cellI = particleCloud_.cellIDs()[index][0];
|
|
||||||
if(cellI >= 0)
|
|
||||||
{
|
|
||||||
voidfraction = voidfraction_[cellI];
|
|
||||||
if (voidfraction < 0.01)
|
|
||||||
voidfraction = 0.01;
|
|
||||||
|
|
||||||
partVolume = particleCloud_.particleVolume(index);
|
|
||||||
QPartPart = QPartPart_[cellI];
|
|
||||||
|
|
||||||
heatFlux(index, partVolume, voidfraction, QPartPart);
|
|
||||||
if (calcTotalHeatFlux_) totalHeatFlux_ += partHeatFlux_[index][0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void heatTransferGranConduction::calcPartEffThermCond()
|
|
||||||
{
|
|
||||||
calcPartThermCond();
|
|
||||||
|
|
||||||
scalar volFrac = 0.0;
|
|
||||||
|
|
||||||
forAll(partEffThermCondField_, cellI)
|
|
||||||
{
|
|
||||||
volFrac = 1.0 - prescribedVoidfraction_[cellI];
|
|
||||||
if (volFrac < 0.334)
|
|
||||||
{
|
|
||||||
partEffThermCondField_[cellI] = 0.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
partEffThermCondField_[cellI] = 0.5 * (3*volFrac - 1) * partThermCondField_[cellI];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void heatTransferGranConduction::calcPartThermCond()
|
|
||||||
{
|
|
||||||
label cellI=0;
|
|
||||||
label partType = 1;
|
|
||||||
double**& partThermCond_ = particleCloud_.getParticlePropertyRef<double**>(partThermCondRegName_);
|
|
||||||
|
|
||||||
for(int index = 0;index < particleCloud_.numberOfParticles(); ++index)
|
|
||||||
{
|
|
||||||
cellI = particleCloud_.cellIDs()[index][0];
|
|
||||||
if (cellI >= 0)
|
|
||||||
{
|
|
||||||
if (multiTypes_)
|
|
||||||
{
|
|
||||||
partType = particleCloud_.particleType(index);
|
|
||||||
}
|
|
||||||
// LIGGGGHTS counts types 1, 2, ..., C++ array starts at 0
|
|
||||||
partThermCond_[index][0] = typePartThermCond_[partType - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
partThermCondField_.primitiveFieldRef() = 0.0;
|
|
||||||
particleCloud_.averagingM().resetWeightFields();
|
|
||||||
particleCloud_.averagingM().setScalarAverage
|
|
||||||
(
|
|
||||||
partThermCondField_,
|
|
||||||
partThermCond_,
|
|
||||||
particleCloud_.particleWeights(),
|
|
||||||
particleCloud_.averagingM().UsWeightField(),
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void heatTransferGranConduction::heatFlux(label index, scalar vol, scalar voidfraction, scalar QPartPart)
|
|
||||||
{
|
|
||||||
double**& partHeatFlux_ = particleCloud_.getParticlePropertyRef<double**>(partHeatFluxName_);
|
|
||||||
partHeatFlux_[index][0] = vol * QPartPart / (1.0 - voidfraction) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
void heatTransferGranConduction::giveData()
|
|
||||||
{
|
|
||||||
if (calcTotalHeatFlux_)
|
|
||||||
{
|
|
||||||
reduce(totalHeatFlux_, sumOp<scalar>());
|
|
||||||
Info << "total conductive particle-particle heat flux [W] (Eulerian) = " << totalHeatFlux_ << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
double**& partHeatFlux_ = particleCloud_.getParticlePropertyRef<double**>(partHeatFluxName_);
|
|
||||||
particleCloud_.dataExchangeM().giveData(partHeatFluxName_,"scalar-atom", partHeatFlux_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void heatTransferGranConduction::postFlow()
|
|
||||||
{
|
|
||||||
giveData();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
|
|
||||||
@ -0,0 +1,468 @@
|
|||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
License
|
||||||
|
|
||||||
|
This 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.
|
||||||
|
|
||||||
|
This code 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 this code. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "error.H"
|
||||||
|
#include "heatTransferInterGrain.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "fvCFD.H"
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(heatTransferInterGrain, 0);
|
||||||
|
|
||||||
|
addToRunTimeSelectionTable(energyModel, heatTransferInterGrain, dictionary);
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Construct from components
|
||||||
|
heatTransferInterGrain::heatTransferInterGrain
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
cfdemCloudEnergy& sm
|
||||||
|
)
|
||||||
|
:
|
||||||
|
energyModel(dict,sm),
|
||||||
|
propsDict_(dict.subDict(typeName + "Props")),
|
||||||
|
multiTypes_(false),
|
||||||
|
verbose_(propsDict_.lookupOrDefault<bool>("verbose",false)),
|
||||||
|
implicit_(propsDict_.lookupOrDefault<bool>("implicit",false)),
|
||||||
|
calcTotalHeatFlux_(propsDict_.lookupOrDefault<bool>("calcTotalHeatFlux",false)),
|
||||||
|
radiativeHeatTransfer_(propsDict_.lookupOrDefault<bool>("radiativeHeatTransfer",false)),
|
||||||
|
totalHeatFlux_(0.0),
|
||||||
|
partTempName_(""),
|
||||||
|
QPartPartName_(propsDict_.lookupOrDefault<word>("QPartPartName","QPartPart")),
|
||||||
|
QPartPart_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
QPartPartName_,
|
||||||
|
sm.mesh().time().timeName(),
|
||||||
|
sm.mesh(),
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
sm.mesh(),
|
||||||
|
dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0), 0.0)
|
||||||
|
),
|
||||||
|
partEffThermCondField_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"partEffThermCondField",
|
||||||
|
sm.mesh().time().timeName(),
|
||||||
|
sm.mesh(),
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
sm.mesh(),
|
||||||
|
dimensionedScalar("one", dimensionSet(1, 1, -3, -1,0,0,0), 1.0),
|
||||||
|
"zeroGradient"
|
||||||
|
),
|
||||||
|
partThermCondField_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"partThermCondField",
|
||||||
|
sm.mesh().time().timeName(),
|
||||||
|
sm.mesh(),
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
sm.mesh(),
|
||||||
|
dimensionedScalar("one", dimensionSet(1, 1, -3, -1,0,0,0), 1.0),
|
||||||
|
"zeroGradient"
|
||||||
|
),
|
||||||
|
partThermCapField_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"partThermCapField",
|
||||||
|
sm.mesh().time().timeName(),
|
||||||
|
sm.mesh(),
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
sm.mesh(),
|
||||||
|
dimensionedScalar("zero", dimensionSet(1,-1,-2,-1,0,0,0), 0.0),
|
||||||
|
"zeroGradient"
|
||||||
|
),
|
||||||
|
partThermRadField_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"partThermRadField",
|
||||||
|
sm.mesh().time().timeName(),
|
||||||
|
sm.mesh(),
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
sm.mesh(),
|
||||||
|
dimensionedScalar("zero", dimensionSet(1, 1, -3, -1,0,0,0), 0.0),
|
||||||
|
"zeroGradient"
|
||||||
|
),
|
||||||
|
partTempField_(sm.mesh().lookupObject<volScalarField>("partTemp")),
|
||||||
|
prescribedVoidfractionFieldName_(propsDict_.lookupOrDefault<word>("prescribedVoidfractionFieldName","voidfraction")),
|
||||||
|
prescribedVoidfraction_(sm.mesh().lookupObject<volScalarField> (prescribedVoidfractionFieldName_)),
|
||||||
|
voidfractionFieldName_(propsDict_.lookupOrDefault<word>("voidfractionFieldName","voidfraction")),
|
||||||
|
voidfraction_(sm.mesh().lookupObject<volScalarField> (voidfractionFieldName_)),
|
||||||
|
typeCG_(propsDict_.lookupOrDefault<scalarList>("coarseGrainingFactors",scalarList(1,1.0))),
|
||||||
|
maxTypeCG_(typeCG_.size()),
|
||||||
|
partHeatFluxName_(propsDict_.lookupOrDefault<word>("partHeatFluxName","conductiveHeatFlux")),
|
||||||
|
typePartThermCond_(propsDict_.lookupOrDefault<scalarList>("thermalConductivities",scalarList(1,-1.0))),
|
||||||
|
partThermCondRegName_(typeName + "partThermCond"),
|
||||||
|
typePartThermCap_(propsDict_.lookupOrDefault<scalarList>("thermalCapacities",scalarList(1,-1.0))),
|
||||||
|
partThermCapRegName_(typeName + "partThermCap"),
|
||||||
|
partThermRadRegName_(typeName + "partThermRad"),
|
||||||
|
StefanBoltzmannConst_(5.67e-8),
|
||||||
|
typePartEmissivity_(propsDict_.lookupOrDefault<scalarList>("thermalEmissivities",scalarList(1,-1.0))),
|
||||||
|
kMax_(propsDict_.lookupOrDefault<scalar>("kMax",-1.0))
|
||||||
|
|
||||||
|
{
|
||||||
|
particleCloud_.registerParticleProperty<double**>(partHeatFluxName_,1);
|
||||||
|
particleCloud_.registerParticleProperty<double**>(partThermCondRegName_,1);
|
||||||
|
if (radiativeHeatTransfer_)
|
||||||
|
{
|
||||||
|
particleCloud_.registerParticleProperty<double**>(partThermRadRegName_,1);
|
||||||
|
partTempName_ = word(propsDict_.lookup("partTempName"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typePartThermCond_[0] < 0.0)
|
||||||
|
{
|
||||||
|
FatalError << "heatTransferInterGrain: provide list of thermal conductivities." << abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typePartEmissivity_[0] < 0.0 && radiativeHeatTransfer_)
|
||||||
|
{
|
||||||
|
FatalError << "heatTransferGranRadiation: provide list of thermal emissivities." << abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typePartEmissivity_[0] > 0.0 && !radiativeHeatTransfer_)
|
||||||
|
{
|
||||||
|
FatalError << "heatTransferGranRadiation: thermal emissivities provided but calculation deactivated." << abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typePartThermCond_.size() > 1)
|
||||||
|
{
|
||||||
|
multiTypes_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multiTypes_ && !particleCloud_.getParticleTypes())
|
||||||
|
{
|
||||||
|
FatalError << "heatTransferInterGrain needs data for more than one type, but types are not communicated." << abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose_)
|
||||||
|
{
|
||||||
|
QPartPart_.writeOpt() = IOobject::AUTO_WRITE;
|
||||||
|
partEffThermCondField_.writeOpt() = IOobject::AUTO_WRITE;
|
||||||
|
partThermCondField_.writeOpt() = IOobject::AUTO_WRITE;
|
||||||
|
partThermCapField_.writeOpt() = IOobject::AUTO_WRITE;
|
||||||
|
partThermRadField_.writeOpt() = IOobject::AUTO_WRITE;
|
||||||
|
QPartPart_.write();
|
||||||
|
partEffThermCondField_.write();
|
||||||
|
partThermCondField_.write();
|
||||||
|
partThermCapField_.write();
|
||||||
|
partThermRadField_.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (implicit_)
|
||||||
|
{
|
||||||
|
particleCloud_.registerParticleProperty<double**>(partThermCapRegName_,1);
|
||||||
|
if (typePartThermCap_[0] < 0.0)
|
||||||
|
{
|
||||||
|
FatalError << "heatTransferInterGrain: provide list of thermal capacities." << abort(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
heatTransferInterGrain::~heatTransferInterGrain()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * //
|
||||||
|
// * * * * * * * * * * * * * * * * Member Fct * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void heatTransferInterGrain::calcEnergyContribution()
|
||||||
|
{
|
||||||
|
calcPartEffThermCond();
|
||||||
|
|
||||||
|
if (kMax_ > 0.0)
|
||||||
|
{
|
||||||
|
dimensionedScalar kMax("kMax",dimensionSet(1,1,-3,-1,0,0,0),kMax_);
|
||||||
|
partEffThermCondField_ = min(partEffThermCondField_,kMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!implicit_)
|
||||||
|
{
|
||||||
|
QPartPart_ = fvc::laplacian(partEffThermCondField_,partTempField_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double**& partThermCap_ = particleCloud_.getParticlePropertyRef<double**>(partThermCapRegName_);
|
||||||
|
label cellI = -1;
|
||||||
|
label partType = -1;
|
||||||
|
for(int index = 0;index < particleCloud_.numberOfParticles(); ++index)
|
||||||
|
{
|
||||||
|
cellI = particleCloud_.cellIDs()[index][0];
|
||||||
|
if (cellI >= 0)
|
||||||
|
{
|
||||||
|
if (multiTypes_)
|
||||||
|
{
|
||||||
|
partType = particleCloud_.particleType(index);
|
||||||
|
}
|
||||||
|
// LIGGGGHTS counts types 1, 2, ..., C++ array starts at 0
|
||||||
|
partThermCap_[index][0] = typePartThermCap_[partType - 1] * particleCloud_.particleDensity(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partThermCapField_.primitiveFieldRef() = 0.0;
|
||||||
|
particleCloud_.averagingM().resetWeightFields();
|
||||||
|
particleCloud_.averagingM().setScalarAverage
|
||||||
|
(
|
||||||
|
partThermCapField_,
|
||||||
|
partThermCap_,
|
||||||
|
particleCloud_.particleWeights(),
|
||||||
|
particleCloud_.averagingM().UsWeightField(),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
partThermCapField_ *= (1.0 - voidfraction_);
|
||||||
|
dimensionedScalar CMin(dimensionedScalar("CMin",dimensionSet(1,-1,-2,-1,0,0,0),SMALL));
|
||||||
|
partThermCapField_ = max(partThermCapField_, CMin);
|
||||||
|
partThermCapField_.oldTime() = partThermCapField_;
|
||||||
|
|
||||||
|
volScalarField partTempField(partTempField_);
|
||||||
|
partTempField.oldTime() = partTempField;
|
||||||
|
fvScalarMatrix TpEqn
|
||||||
|
(
|
||||||
|
fvm::ddt(partThermCapField_,partTempField)
|
||||||
|
==
|
||||||
|
fvm::laplacian(partEffThermCondField_,partTempField)
|
||||||
|
);
|
||||||
|
|
||||||
|
TpEqn.solve();
|
||||||
|
QPartPart_ = fvc::laplacian(partEffThermCondField_,partTempField);
|
||||||
|
}
|
||||||
|
|
||||||
|
label cellI=0;
|
||||||
|
scalar partVolume(0);
|
||||||
|
scalar QPartPart(0);
|
||||||
|
scalar voidfraction(1);
|
||||||
|
|
||||||
|
totalHeatFlux_ = 0.0;
|
||||||
|
double**& partHeatFlux_ = particleCloud_.getParticlePropertyRef<double**>(partHeatFluxName_);
|
||||||
|
|
||||||
|
for(int index = 0;index < particleCloud_.numberOfParticles(); ++index)
|
||||||
|
{
|
||||||
|
cellI = particleCloud_.cellIDs()[index][0];
|
||||||
|
if(cellI >= 0)
|
||||||
|
{
|
||||||
|
voidfraction = voidfraction_[cellI];
|
||||||
|
if (voidfraction < 0.01)
|
||||||
|
voidfraction = 0.01;
|
||||||
|
|
||||||
|
partVolume = particleCloud_.particleVolume(index);
|
||||||
|
QPartPart = QPartPart_[cellI];
|
||||||
|
|
||||||
|
heatFlux(index, partVolume, voidfraction, QPartPart);
|
||||||
|
if (calcTotalHeatFlux_) totalHeatFlux_ += partHeatFlux_[index][0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void heatTransferInterGrain::calcPartEffThermCond()
|
||||||
|
{
|
||||||
|
calcPartThermCond();
|
||||||
|
if (radiativeHeatTransfer_) calcPartThermRad();
|
||||||
|
|
||||||
|
scalar volFrac = 0.0;
|
||||||
|
|
||||||
|
if (!radiativeHeatTransfer_)
|
||||||
|
{
|
||||||
|
forAll(partEffThermCondField_, cellI)
|
||||||
|
{
|
||||||
|
volFrac = 1.0 - prescribedVoidfraction_[cellI];
|
||||||
|
if (volFrac < 0.334)
|
||||||
|
{
|
||||||
|
partEffThermCondField_[cellI] = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
partEffThermCondField_[cellI] = 0.5 * (3*volFrac - 1) * partThermCondField_[cellI];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scalar thRad = 0.0;
|
||||||
|
forAll(partEffThermCondField_, cellI)
|
||||||
|
{
|
||||||
|
volFrac = 1.0 - prescribedVoidfraction_[cellI];
|
||||||
|
thRad = volFrac * partThermRadField_[cellI]; // volume fraction factor for rad. contribution according to Qian et al.
|
||||||
|
if (volFrac < 0.334)
|
||||||
|
{
|
||||||
|
partEffThermCondField_[cellI] = thRad;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
partEffThermCondField_[cellI] = 0.5 * (3*volFrac - 1) * partThermCondField_[cellI] + thRad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void heatTransferInterGrain::calcPartThermCond()
|
||||||
|
{
|
||||||
|
label cellI=0;
|
||||||
|
label partType = 1;
|
||||||
|
double**& partThermCond_ = particleCloud_.getParticlePropertyRef<double**>(partThermCondRegName_);
|
||||||
|
|
||||||
|
for(int index = 0;index < particleCloud_.numberOfParticles(); ++index)
|
||||||
|
{
|
||||||
|
cellI = particleCloud_.cellIDs()[index][0];
|
||||||
|
if (cellI >= 0)
|
||||||
|
{
|
||||||
|
if (multiTypes_)
|
||||||
|
{
|
||||||
|
partType = particleCloud_.particleType(index);
|
||||||
|
}
|
||||||
|
// LIGGGGHTS counts types 1, 2, ..., C++ array starts at 0
|
||||||
|
partThermCond_[index][0] = typePartThermCond_[partType - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partThermCondField_.primitiveFieldRef() = 0.0;
|
||||||
|
particleCloud_.averagingM().resetWeightFields();
|
||||||
|
particleCloud_.averagingM().setScalarAverage
|
||||||
|
(
|
||||||
|
partThermCondField_,
|
||||||
|
partThermCond_,
|
||||||
|
particleCloud_.particleWeights(),
|
||||||
|
particleCloud_.averagingM().UsWeightField(),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void heatTransferInterGrain::calcPartThermRad()
|
||||||
|
{
|
||||||
|
label cellI=0;
|
||||||
|
label partType = 1;
|
||||||
|
scalar cg = typeCG_[0];
|
||||||
|
scalar ds = 0.0;
|
||||||
|
scalar L = 0.0;
|
||||||
|
scalar prefac = 0.0;
|
||||||
|
scalar Tp = 0.0;
|
||||||
|
scalar voidfraction = 0.0;
|
||||||
|
|
||||||
|
double**& partTemp_ = particleCloud_.getParticlePropertyRef<double**>(partTempName_);
|
||||||
|
double**& partThermCond_ = particleCloud_.getParticlePropertyRef<double**>(partThermCondRegName_);
|
||||||
|
double**& partThermRad_ = particleCloud_.getParticlePropertyRef<double**>(partThermRadRegName_);
|
||||||
|
|
||||||
|
for(int index = 0;index < particleCloud_.numberOfParticles(); ++index)
|
||||||
|
{
|
||||||
|
cellI = particleCloud_.cellIDs()[index][0];
|
||||||
|
if (cellI >= 0)
|
||||||
|
{
|
||||||
|
if (multiTypes_)
|
||||||
|
{
|
||||||
|
partType = particleCloud_.particleType(index);
|
||||||
|
if (partType > maxTypeCG_)
|
||||||
|
{
|
||||||
|
FatalError<< "Too few coarse-graining factors provided." << abort(FatalError);
|
||||||
|
}
|
||||||
|
cg = typeCG_[partType - 1];
|
||||||
|
}
|
||||||
|
ds = 2.*particleCloud_.radius(index)/cg;
|
||||||
|
// make sure reasonable values are used
|
||||||
|
Tp = partTemp_[index][0];
|
||||||
|
if (Tp < TMin) Tp = TMin;
|
||||||
|
voidfraction = prescribedVoidfraction_[cellI];
|
||||||
|
if (voidfraction < voidfracMin) voidfraction = voidfracMin;
|
||||||
|
else if (voidfraction > voidfracMax) voidfraction = voidfracMax;
|
||||||
|
|
||||||
|
prefac = 4.0*StefanBoltzmannConst_*ds*Tp*Tp*Tp;
|
||||||
|
L = partThermCond_[index][0]/prefac;
|
||||||
|
// LIGGGGHTS counts types 1, 2, ..., C++ array starts at 0
|
||||||
|
partThermRad_[index][0] = prefac*FE(voidfraction,typePartEmissivity_[partType - 1],L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
partThermRadField_.primitiveFieldRef() = 0.0;
|
||||||
|
particleCloud_.averagingM().resetWeightFields();
|
||||||
|
particleCloud_.averagingM().setScalarAverage
|
||||||
|
(
|
||||||
|
partThermRadField_,
|
||||||
|
partThermRad_,
|
||||||
|
particleCloud_.particleWeights(),
|
||||||
|
particleCloud_.averagingM().UsWeightField(),
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
scalar heatTransferInterGrain::FE(scalar voidfraction, scalar emissivity, scalar L)
|
||||||
|
{
|
||||||
|
if (voidfraction < 1 - SMALL) return 1.0; // limit of voidfraction -> 1.0
|
||||||
|
|
||||||
|
scalar B = 1.25 * pow((1-voidfraction)/voidfraction,1.111);
|
||||||
|
scalar sqrt_aP = sqrt(1-voidfraction);
|
||||||
|
scalar x = 2.0/emissivity - 1.0;
|
||||||
|
scalar y = 1.0 / (x*L);
|
||||||
|
scalar z = sqrt_aP / (2.0/emissivity - 1.0) * (B+1.0)/B * 1.0/(1.0 + y);
|
||||||
|
return (1 - sqrt_aP)*voidfraction + z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void heatTransferInterGrain::heatFlux(label index, scalar vol, scalar voidfraction, scalar QPartPart)
|
||||||
|
{
|
||||||
|
double**& partHeatFlux_ = particleCloud_.getParticlePropertyRef<double**>(partHeatFluxName_);
|
||||||
|
partHeatFlux_[index][0] = vol * QPartPart / (1.0 - voidfraction) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void heatTransferInterGrain::giveData()
|
||||||
|
{
|
||||||
|
if (calcTotalHeatFlux_)
|
||||||
|
{
|
||||||
|
reduce(totalHeatFlux_, sumOp<scalar>());
|
||||||
|
Info << "total conductive particle-particle heat flux [W] (Eulerian) = " << totalHeatFlux_ << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
double**& partHeatFlux_ = particleCloud_.getParticlePropertyRef<double**>(partHeatFluxName_);
|
||||||
|
particleCloud_.dataExchangeM().giveData(partHeatFluxName_,"scalar-atom", partHeatFlux_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void heatTransferInterGrain::postFlow()
|
||||||
|
{
|
||||||
|
giveData();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
|
|
||||||
@ -19,12 +19,16 @@ License
|
|||||||
Description
|
Description
|
||||||
heat transfer from granular conduction according to the
|
heat transfer from granular conduction according to the
|
||||||
Effective Medium Theory discussed e.g. by
|
Effective Medium Theory discussed e.g. by
|
||||||
Carson et al. Int. J. Heat Mass Transfer 48 (2005)
|
Carson et al. Int. J. Heat Mass Transfer 48 (2005) 2150–2158
|
||||||
|
optional radiative contribution according to
|
||||||
|
G. Breitbach, H. Barthels. Nucl. Technol. 49 (1980) 392–399
|
||||||
|
as discussed in
|
||||||
|
Qian et al. Int. J. Heat Mass Transf. 127 (2018) 573–584
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef heatTransferGranConduction_H
|
#ifndef heatTransferInterGrain_H
|
||||||
#define heatTransferGranConduction_H
|
#define heatTransferInterGrain_H
|
||||||
|
|
||||||
#include "fvCFD.H"
|
#include "fvCFD.H"
|
||||||
#include "cfdemCloudEnergy.H"
|
#include "cfdemCloudEnergy.H"
|
||||||
@ -35,10 +39,10 @@ namespace Foam
|
|||||||
{
|
{
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class heatTransferGranConduction Declaration
|
Class heatTransferInterGrain Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class heatTransferGranConduction
|
class heatTransferInterGrain
|
||||||
:
|
:
|
||||||
public energyModel
|
public energyModel
|
||||||
{
|
{
|
||||||
@ -50,10 +54,16 @@ protected:
|
|||||||
|
|
||||||
bool verbose_;
|
bool verbose_;
|
||||||
|
|
||||||
|
bool implicit_;
|
||||||
|
|
||||||
bool calcTotalHeatFlux_;
|
bool calcTotalHeatFlux_;
|
||||||
|
|
||||||
|
bool radiativeHeatTransfer_;
|
||||||
|
|
||||||
scalar totalHeatFlux_;
|
scalar totalHeatFlux_;
|
||||||
|
|
||||||
|
word partTempName_;
|
||||||
|
|
||||||
const word QPartPartName_;
|
const word QPartPartName_;
|
||||||
|
|
||||||
volScalarField QPartPart_;
|
volScalarField QPartPart_;
|
||||||
@ -62,6 +72,10 @@ protected:
|
|||||||
|
|
||||||
volScalarField partThermCondField_;
|
volScalarField partThermCondField_;
|
||||||
|
|
||||||
|
volScalarField partThermCapField_;
|
||||||
|
|
||||||
|
volScalarField partThermRadField_;
|
||||||
|
|
||||||
const volScalarField& partTempField_;
|
const volScalarField& partTempField_;
|
||||||
|
|
||||||
const word prescribedVoidfractionFieldName_;
|
const word prescribedVoidfractionFieldName_;
|
||||||
@ -72,16 +86,42 @@ protected:
|
|||||||
|
|
||||||
const volScalarField& voidfraction_;
|
const volScalarField& voidfraction_;
|
||||||
|
|
||||||
|
scalarList typeCG_;
|
||||||
|
|
||||||
|
const label maxTypeCG_;
|
||||||
|
|
||||||
const word partHeatFluxName_;
|
const word partHeatFluxName_;
|
||||||
|
|
||||||
scalarList typePartThermCond_;
|
scalarList typePartThermCond_;
|
||||||
|
|
||||||
const word partThermCondRegName_;
|
const word partThermCondRegName_;
|
||||||
|
|
||||||
|
scalarList typePartThermCap_;
|
||||||
|
|
||||||
|
const word partThermCapRegName_;
|
||||||
|
|
||||||
|
const word partThermRadRegName_;
|
||||||
|
|
||||||
|
const scalar TMin = 10.0;
|
||||||
|
|
||||||
|
const scalar voidfracMax = 0.95;
|
||||||
|
|
||||||
|
const scalar voidfracMin = 0.05;
|
||||||
|
|
||||||
|
const scalar StefanBoltzmannConst_;
|
||||||
|
|
||||||
|
scalarList typePartEmissivity_;
|
||||||
|
|
||||||
|
scalar kMax_;
|
||||||
|
|
||||||
void calcPartEffThermCond();
|
void calcPartEffThermCond();
|
||||||
|
|
||||||
void calcPartThermCond();
|
void calcPartThermCond();
|
||||||
|
|
||||||
|
void calcPartThermRad();
|
||||||
|
|
||||||
|
scalar FE(scalar, scalar, scalar);
|
||||||
|
|
||||||
virtual void giveData();
|
virtual void giveData();
|
||||||
|
|
||||||
virtual void heatFlux(label, scalar, scalar, scalar);
|
virtual void heatFlux(label, scalar, scalar, scalar);
|
||||||
@ -91,12 +131,12 @@ protected:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
TypeName("heatTransferGranConduction");
|
TypeName("heatTransferInterGrain");
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from components
|
//- Construct from components
|
||||||
heatTransferGranConduction
|
heatTransferInterGrain
|
||||||
(
|
(
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
cfdemCloudEnergy& sm
|
cfdemCloudEnergy& sm
|
||||||
@ -105,7 +145,7 @@ public:
|
|||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
|
|
||||||
virtual ~heatTransferGranConduction();
|
virtual ~heatTransferInterGrain();
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
@ -47,6 +47,7 @@ reactionHeat::reactionHeat
|
|||||||
propsDict_(dict.subDict(typeName + "Props")),
|
propsDict_(dict.subDict(typeName + "Props")),
|
||||||
interpolation_(propsDict_.lookupOrDefault<bool>("interpolation",false)),
|
interpolation_(propsDict_.lookupOrDefault<bool>("interpolation",false)),
|
||||||
verbose_(propsDict_.lookupOrDefault<bool>("verbose",false)),
|
verbose_(propsDict_.lookupOrDefault<bool>("verbose",false)),
|
||||||
|
execution_(true),
|
||||||
mesh_(sm.mesh()),
|
mesh_(sm.mesh()),
|
||||||
maxSource_(1e30),
|
maxSource_(1e30),
|
||||||
reactionHeatName_(propsDict_.lookupOrDefault<word>("reactionHeatName","reactionHeat")),
|
reactionHeatName_(propsDict_.lookupOrDefault<word>("reactionHeatName","reactionHeat")),
|
||||||
@ -62,8 +63,14 @@ reactionHeat::reactionHeat
|
|||||||
),
|
),
|
||||||
mesh_,
|
mesh_,
|
||||||
dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0),0.0)
|
dimensionedScalar("zero", dimensionSet(1,-1,-3,0,0,0,0),0.0)
|
||||||
)
|
),
|
||||||
|
Nevery_(propsDict_.lookupOrDefault<label>("Nevery",1)),
|
||||||
|
couplingTimestep_(0.0)
|
||||||
{
|
{
|
||||||
|
scalar dtDEM = particleCloud_.dataExchangeM().DEMts();
|
||||||
|
scalar dtCFD = mesh_.time().deltaTValue();
|
||||||
|
couplingTimestep_ = max(dtDEM,dtCFD);
|
||||||
|
|
||||||
particleCloud_.registerParticleProperty<double**>(reactionHeatName_,1);
|
particleCloud_.registerParticleProperty<double**>(reactionHeatName_,1);
|
||||||
|
|
||||||
if(propsDict_.found("maxsource"))
|
if(propsDict_.found("maxsource"))
|
||||||
@ -86,6 +93,12 @@ reactionHeat::~reactionHeat()
|
|||||||
|
|
||||||
void reactionHeat::calcEnergyContribution()
|
void reactionHeat::calcEnergyContribution()
|
||||||
{
|
{
|
||||||
|
execution_ = (particleCloud_.dataExchangeM().couplingStep() % Nevery_ == 0);
|
||||||
|
if (!execution_)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
double**& reactionHeat_ = particleCloud_.getParticlePropertyRef<double**>(reactionHeatName_);
|
double**& reactionHeat_ = particleCloud_.getParticlePropertyRef<double**>(reactionHeatName_);
|
||||||
|
|
||||||
particleCloud_.dataExchangeM().getData(reactionHeatName_,"scalar-atom",reactionHeat_);
|
particleCloud_.dataExchangeM().getData(reactionHeatName_,"scalar-atom",reactionHeat_);
|
||||||
@ -109,7 +122,7 @@ void reactionHeat::calcEnergyContribution()
|
|||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
reactionHeatField_.primitiveFieldRef() /= (reactionHeatField_.mesh().V());
|
reactionHeatField_.primitiveFieldRef() /= (reactionHeatField_.mesh().V() * Nevery_ * couplingTimestep_);
|
||||||
|
|
||||||
forAll(reactionHeatField_,cellI)
|
forAll(reactionHeatField_,cellI)
|
||||||
{
|
{
|
||||||
@ -121,6 +134,12 @@ void reactionHeat::calcEnergyContribution()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (verbose_)
|
||||||
|
{
|
||||||
|
Info << "reaction heat per unit time = "
|
||||||
|
<< gSum(reactionHeatField_*1.0*reactionHeatField_.mesh().V()) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
reactionHeatField_.correctBoundaryConditions();
|
reactionHeatField_.correctBoundaryConditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -50,6 +50,8 @@ protected:
|
|||||||
|
|
||||||
bool verbose_;
|
bool verbose_;
|
||||||
|
|
||||||
|
bool execution_;
|
||||||
|
|
||||||
const fvMesh& mesh_;
|
const fvMesh& mesh_;
|
||||||
|
|
||||||
scalar maxSource_;
|
scalar maxSource_;
|
||||||
@ -58,6 +60,10 @@ protected:
|
|||||||
|
|
||||||
volScalarField reactionHeatField_;
|
volScalarField reactionHeatField_;
|
||||||
|
|
||||||
|
label Nevery_;
|
||||||
|
|
||||||
|
scalar couplingTimestep_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
|
|||||||
@ -53,14 +53,30 @@ particleDeformation::particleDeformation
|
|||||||
initialExec_(true),
|
initialExec_(true),
|
||||||
refFieldName_(propsDict_.lookup("refFieldName")),
|
refFieldName_(propsDict_.lookup("refFieldName")),
|
||||||
refField_(),
|
refField_(),
|
||||||
|
voidfractionFieldName_(propsDict_.lookupOrDefault<word>("voidfractionFieldName","voidfraction")),
|
||||||
|
#if OPENFOAM_VERSION_MAJOR < 5
|
||||||
|
voidfraction_(const_cast<volScalarField&>(sm.mesh().lookupObject<volScalarField>(voidfractionFieldName_))),
|
||||||
|
#else
|
||||||
|
voidfraction_(sm.mesh().lookupObjectRef<volScalarField> (voidfractionFieldName_)),
|
||||||
|
#endif
|
||||||
defaultDeformCellsName_(propsDict_.lookupOrDefault<word>("defaultDeformCellsName","none")),
|
defaultDeformCellsName_(propsDict_.lookupOrDefault<word>("defaultDeformCellsName","none")),
|
||||||
defaultDeformCells_(),
|
defaultDeformCells_(),
|
||||||
existDefaultDeformCells_(false),
|
existDefaultDeformCells_(false),
|
||||||
defaultDeformation_(propsDict_.lookupOrDefault<scalar>("defaultDeformation",1.0)),
|
defaultDeformation_(propsDict_.lookupOrDefault<scalar>("defaultDeformation",1.0)),
|
||||||
|
existBackgroundVoidage_(false),
|
||||||
|
backgroundVoidage_(propsDict_.lookupOrDefault<scalar>("backgroundVoidage",-1.0)),
|
||||||
|
backgroundRef_(propsDict_.lookupOrDefault<scalar>("backgroundRef",0.35)),
|
||||||
partTypes_(propsDict_.lookupOrDefault<labelList>("partTypes",labelList(1,-1))),
|
partTypes_(propsDict_.lookupOrDefault<labelList>("partTypes",labelList(1,-1))),
|
||||||
lowerBounds_(propsDict_.lookupOrDefault<scalarList>("lowerBounds",scalarList(1,-1.0))),
|
lowerBounds_(propsDict_.lookupOrDefault<scalarList>("lowerBounds",scalarList(1,-1.0))),
|
||||||
upperBounds_(propsDict_.lookupOrDefault<scalarList>("upperBounds",scalarList(1,-1.0))),
|
upperBounds_(propsDict_.lookupOrDefault<scalarList>("upperBounds",scalarList(1,-1.0))),
|
||||||
partDeformationsName_("partDeformations")
|
partDeformationsName_("partDeformations"),
|
||||||
|
controlForceOnDefPart_(propsDict_.lookupOrDefault<bool>("controlForceOnDefPart",false)),
|
||||||
|
controlFieldName_(propsDict_.lookupOrDefault<word>("controlFieldName","")),
|
||||||
|
controlField_(NULL),
|
||||||
|
controlPoint_(propsDict_.lookupOrDefault<vector>("controlPoint",vector::zero)),
|
||||||
|
controlCell_(-1),
|
||||||
|
controlTargetValue_(propsDict_.lookupOrDefault<scalar>("controlTargetValue",0.0)),
|
||||||
|
controlCouplingStrength_(propsDict_.lookupOrDefault<scalar>("controlCouplingStrength",0.0))
|
||||||
{
|
{
|
||||||
particleCloud_.registerParticleProperty<double**>(partDeformationsName_,1);
|
particleCloud_.registerParticleProperty<double**>(partDeformationsName_,1);
|
||||||
|
|
||||||
@ -89,6 +105,11 @@ particleDeformation::particleDeformation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (backgroundVoidage_ <= 1.0 && backgroundVoidage_ >= 0.01)
|
||||||
|
{
|
||||||
|
existBackgroundVoidage_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
// check if only single value instead of list was provided
|
// check if only single value instead of list was provided
|
||||||
if (propsDict_.found("partType"))
|
if (propsDict_.found("partType"))
|
||||||
{
|
{
|
||||||
@ -113,6 +134,11 @@ particleDeformation::particleDeformation
|
|||||||
Info << "partTypes: " << partTypes_ << endl;
|
Info << "partTypes: " << partTypes_ << endl;
|
||||||
Info << "lowerBounds: " << lowerBounds_ << endl;
|
Info << "lowerBounds: " << lowerBounds_ << endl;
|
||||||
Info << "upperBounds: " << upperBounds_ << endl;
|
Info << "upperBounds: " << upperBounds_ << endl;
|
||||||
|
|
||||||
|
if (controlForceOnDefPart_)
|
||||||
|
{
|
||||||
|
controlCell_ = sm.mesh().findCell(controlPoint_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -139,6 +165,16 @@ void particleDeformation::setForce() const
|
|||||||
initialExec_ = false;
|
initialExec_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scalar controlCurrValue = 0.0;
|
||||||
|
scalar scaleFactor = 0.0;
|
||||||
|
if (controlForceOnDefPart_)
|
||||||
|
{
|
||||||
|
controlCurrValue = (*controlField_)[controlCell_];
|
||||||
|
reduce(controlCurrValue, sumOp<scalar>());
|
||||||
|
scaleFactor = 1.0 + controlCouplingStrength_ * (controlTargetValue_ - controlCurrValue);
|
||||||
|
Info << "particleDeformation: scaleFactor = " << scaleFactor << endl;
|
||||||
|
}
|
||||||
|
|
||||||
double**& partDeformations_ = particleCloud_.getParticlePropertyRef<double**>(partDeformationsName_);
|
double**& partDeformations_ = particleCloud_.getParticlePropertyRef<double**>(partDeformationsName_);
|
||||||
|
|
||||||
label cellI = 0;
|
label cellI = 0;
|
||||||
@ -187,6 +223,15 @@ void particleDeformation::setForce() const
|
|||||||
|
|
||||||
partDeformations_[index][0] = deformationDegree;
|
partDeformations_[index][0] = deformationDegree;
|
||||||
|
|
||||||
|
if (existBackgroundVoidage_ && deformationDegree > 0.1)
|
||||||
|
{
|
||||||
|
voidfraction_[cellI] = backgroundRef_ + deformationDegree * (backgroundVoidage_ - backgroundRef_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controlForceOnDefPart_)
|
||||||
|
{
|
||||||
|
particleCloud_.scaleForce(index,scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
if(forceSubM(0).verbose() && index >= 0 && index < 2)
|
if(forceSubM(0).verbose() && index >= 0 && index < 2)
|
||||||
{
|
{
|
||||||
@ -222,12 +267,18 @@ void particleDeformation::init() const
|
|||||||
particleCloud_.mesh().time().timeName(tstart),
|
particleCloud_.mesh().time().timeName(tstart),
|
||||||
particleCloud_.mesh(),
|
particleCloud_.mesh(),
|
||||||
IOobject::MUST_READ,
|
IOobject::MUST_READ,
|
||||||
IOobject::NO_WRITE
|
IOobject::AUTO_WRITE
|
||||||
),
|
),
|
||||||
particleCloud_.mesh()
|
particleCloud_.mesh()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (controlForceOnDefPart_)
|
||||||
|
{
|
||||||
|
volScalarField& controlField(const_cast<volScalarField&>(particleCloud_.mesh().lookupObject<volScalarField> (controlFieldName_)));
|
||||||
|
controlField_ = &controlField;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
label particleDeformation::getListIndex(label testElement) const
|
label particleDeformation::getListIndex(label testElement) const
|
||||||
|
|||||||
@ -59,6 +59,10 @@ private:
|
|||||||
|
|
||||||
mutable autoPtr<volScalarField> refField_;
|
mutable autoPtr<volScalarField> refField_;
|
||||||
|
|
||||||
|
word voidfractionFieldName_;
|
||||||
|
|
||||||
|
volScalarField& voidfraction_;
|
||||||
|
|
||||||
// default deformation in region
|
// default deformation in region
|
||||||
const word defaultDeformCellsName_;
|
const word defaultDeformCellsName_;
|
||||||
|
|
||||||
@ -68,6 +72,12 @@ private:
|
|||||||
|
|
||||||
scalar defaultDeformation_;
|
scalar defaultDeformation_;
|
||||||
|
|
||||||
|
bool existBackgroundVoidage_;
|
||||||
|
|
||||||
|
scalar backgroundVoidage_;
|
||||||
|
|
||||||
|
scalar backgroundRef_;
|
||||||
|
|
||||||
labelList partTypes_;
|
labelList partTypes_;
|
||||||
|
|
||||||
scalarList lowerBounds_;
|
scalarList lowerBounds_;
|
||||||
@ -76,6 +86,22 @@ private:
|
|||||||
|
|
||||||
const word partDeformationsName_;
|
const word partDeformationsName_;
|
||||||
|
|
||||||
|
// control functionality
|
||||||
|
|
||||||
|
bool controlForceOnDefPart_;
|
||||||
|
|
||||||
|
word controlFieldName_;
|
||||||
|
|
||||||
|
mutable volScalarField* controlField_;
|
||||||
|
|
||||||
|
vector controlPoint_;
|
||||||
|
|
||||||
|
label controlCell_;
|
||||||
|
|
||||||
|
scalar controlTargetValue_;
|
||||||
|
|
||||||
|
scalar controlCouplingStrength_;
|
||||||
|
|
||||||
label getListIndex(label) const;
|
label getListIndex(label) const;
|
||||||
|
|
||||||
void init() const;
|
void init() const;
|
||||||
|
|||||||
@ -0,0 +1,263 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
CFDEMcoupling academic - Open Source CFD-DEM coupling
|
||||||
|
|
||||||
|
Contributing authors:
|
||||||
|
Thomas Lichtenegger, Sanaz Abbasi
|
||||||
|
Copyright (C) 2015- Johannes Kepler University, Linz
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of CFDEMcoupling academic.
|
||||||
|
|
||||||
|
CFDEMcoupling academic 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.
|
||||||
|
|
||||||
|
CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "error.H"
|
||||||
|
|
||||||
|
#include "terminalVelocity.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(terminalVelocity, 0);
|
||||||
|
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
forceModel,
|
||||||
|
terminalVelocity,
|
||||||
|
dictionary
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Construct from components
|
||||||
|
terminalVelocity::terminalVelocity
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
cfdemCloud& sm
|
||||||
|
)
|
||||||
|
:
|
||||||
|
forceModel(dict,sm),
|
||||||
|
propsDict_(dict.subDict(typeName + "Props")),
|
||||||
|
interpolate_(propsDict_.lookupOrDefault<bool>("interpolation", false)),
|
||||||
|
mesh_(sm.mesh()),
|
||||||
|
ignoreCellsName_(propsDict_.lookupOrDefault<word>("ignoreCellsName","none")),
|
||||||
|
ignoreCells_(),
|
||||||
|
existIgnoreCells_(true),
|
||||||
|
existturbDissipationRateInObjReg_(false),
|
||||||
|
turbulenceCorrection_(propsDict_.lookupOrDefault<bool>("turbulenceCorrection",false)),
|
||||||
|
turbDissipationRate_(NULL),
|
||||||
|
wallIndicatorField_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"wallIndicator",
|
||||||
|
sm.mesh().time().timeName(),
|
||||||
|
sm.mesh(),
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
sm.mesh(),
|
||||||
|
dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0)
|
||||||
|
),
|
||||||
|
liquidViscosity_(propsDict_.lookupOrDefault<scalar>("liquidViscosity", 1.0)),
|
||||||
|
dragReductionFactor_(propsDict_.lookupOrDefault<scalar>("dragReductionFactor", 0.0)),
|
||||||
|
gravityFieldName_(propsDict_.lookupOrDefault<word>("gravityFieldName","g")),
|
||||||
|
g_(sm.mesh().lookupObject<uniformDimensionedVectorField> (gravityFieldName_))
|
||||||
|
{
|
||||||
|
// init force sub model
|
||||||
|
setForceSubModels(propsDict_);
|
||||||
|
// define switches which can be read from dict
|
||||||
|
forceSubM(0).setSwitchesList(SW_VERBOSE,true); // activate search for verbose switch
|
||||||
|
// TODO: remove bool interpolate for this class, let forceSubModel do this
|
||||||
|
// forceSubM(0).setSwitchesList(SW_INTERPOLATION,true); // activate search for interpolate switch
|
||||||
|
forceSubM(0).readSwitches();
|
||||||
|
|
||||||
|
scalar terminalVelMagnitude(propsDict_.lookupOrDefault<scalar>("terminalVelocity", 0.0));
|
||||||
|
terminalVel_ = -terminalVelMagnitude * g_.value() / mag(g_.value());
|
||||||
|
|
||||||
|
if (ignoreCellsName_ != "none")
|
||||||
|
{
|
||||||
|
ignoreCells_.set(new cellSet(particleCloud_.mesh(),ignoreCellsName_));
|
||||||
|
Info<< "terminalVelocity: ignoring rising velocity in cellSet " << ignoreCells_().name()
|
||||||
|
<< " with " << ignoreCells_().size() << " cells." << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
existIgnoreCells_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
turbDissipationRate_ = new volScalarField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"turbDissipationRate",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensionedScalar("zero", dimensionSet(0,2,-3,0,0), 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
// define a field to indicate if a cell is next to boundary
|
||||||
|
label cellI = -1;
|
||||||
|
forAll(mesh_.boundary(), patchI)
|
||||||
|
{
|
||||||
|
word patchName = mesh_.boundary()[patchI].name();
|
||||||
|
if (patchName.rfind("procB",0) == 0) continue;
|
||||||
|
|
||||||
|
forAll(mesh_.boundary()[patchI], faceI)
|
||||||
|
{
|
||||||
|
cellI = mesh_.boundary()[patchI].faceCells()[faceI];
|
||||||
|
wallIndicatorField_[cellI] = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
terminalVelocity::~terminalVelocity()
|
||||||
|
{
|
||||||
|
if (!existturbDissipationRateInObjReg_) delete turbDissipationRate_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool terminalVelocity::ignoreCell(label cell) const
|
||||||
|
{
|
||||||
|
if (!existIgnoreCells_) return false;
|
||||||
|
else return ignoreCells_()[cell];
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void terminalVelocity::setForce() const
|
||||||
|
{
|
||||||
|
updateEpsilon();
|
||||||
|
|
||||||
|
vector position(0,0,0);
|
||||||
|
label cellI = -1;
|
||||||
|
scalar radius = 0.0;
|
||||||
|
scalar epsilon = 0.0;
|
||||||
|
scalar dLambda = 0.0;
|
||||||
|
scalar velReductionFactor = 0.0;
|
||||||
|
vector Uparticle(0,0,0);
|
||||||
|
|
||||||
|
label patchID = -1;
|
||||||
|
label faceIGlobal = -1;
|
||||||
|
scalar velProjection = 0.0;
|
||||||
|
vector faceINormal = vector::zero;
|
||||||
|
word patchName("");
|
||||||
|
|
||||||
|
interpolationCellPoint<scalar> turbDissipationRateInterpolator_(*turbDissipationRate_);
|
||||||
|
|
||||||
|
for (int index = 0; index < particleCloud_.numberOfParticles(); ++index)
|
||||||
|
{
|
||||||
|
cellI = particleCloud_.cellIDs()[index][0];
|
||||||
|
Uparticle = vector::zero;
|
||||||
|
|
||||||
|
if (cellI > -1 && !ignoreCell(cellI)) // particle found
|
||||||
|
{
|
||||||
|
if (interpolate_)
|
||||||
|
{
|
||||||
|
position = particleCloud_.position(index);
|
||||||
|
epsilon = turbDissipationRateInterpolator_.interpolate(position,cellI);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
epsilon = (*turbDissipationRate_)[cellI];
|
||||||
|
}
|
||||||
|
|
||||||
|
position = particleCloud_.position(index);
|
||||||
|
radius = particleCloud_.radius(index);
|
||||||
|
|
||||||
|
if (turbulenceCorrection_)
|
||||||
|
{
|
||||||
|
// d * kolmogorov length scale
|
||||||
|
dLambda = 2*radius*pow(epsilon,0.25)/pow(liquidViscosity_,0.75);
|
||||||
|
velReductionFactor = Foam::sqrt(1 + (dragReductionFactor_*pow(dLambda,3)));
|
||||||
|
terminalVel_ = terminalVel_ / velReductionFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the new particle velocity
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
particleCloud_.particleConvVels()[index][j] += terminalVel_[j];
|
||||||
|
Uparticle[j] = particleCloud_.particleConvVels()[index][j];
|
||||||
|
}
|
||||||
|
|
||||||
|
// prevent particles being pushed through walls
|
||||||
|
// check if cell is adjacent to wall and remove the normal velocity to the wall
|
||||||
|
if (wallIndicatorField_[cellI] > 0.5)
|
||||||
|
{
|
||||||
|
const cell& faces = mesh_.cells()[cellI];
|
||||||
|
forAll(faces, faceI)
|
||||||
|
{
|
||||||
|
faceIGlobal = faces[faceI];
|
||||||
|
patchID = mesh_.boundaryMesh().whichPatch(faceIGlobal);
|
||||||
|
if (patchID < 0) continue;
|
||||||
|
patchName = mesh_.boundary()[patchID].name();
|
||||||
|
|
||||||
|
if (patchName.rfind("procB",0) == 0) continue;
|
||||||
|
|
||||||
|
faceINormal = mesh_.Sf()[faceIGlobal];
|
||||||
|
faceINormal /= mag(faceINormal);
|
||||||
|
velProjection = faceINormal&Uparticle;
|
||||||
|
if (velProjection > 0.0)
|
||||||
|
{
|
||||||
|
// removes the value normal to the face
|
||||||
|
for (int j = 0; j < 3; j++)
|
||||||
|
{
|
||||||
|
particleCloud_.particleConvVels()[index][j] -= velProjection*faceINormal[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forceSubM(0).verbose() && index > 0 && index < 2)
|
||||||
|
{
|
||||||
|
Pout<< "cellI = " << cellI << endl;
|
||||||
|
Pout<< "index = " << index << endl;
|
||||||
|
Pout<< "epsilon = " << epsilon << endl;
|
||||||
|
Pout<< "rising velocity = " << terminalVel_ << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void terminalVelocity::updateEpsilon() const
|
||||||
|
{
|
||||||
|
if (!existturbDissipationRateInObjReg_)
|
||||||
|
{
|
||||||
|
Info<< "epsilon is calculated from the turbulence model. " << endl;
|
||||||
|
*turbDissipationRate_ = particleCloud_.turbulence().epsilon()();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,130 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
CFDEMcoupling academic - Open Source CFD-DEM coupling
|
||||||
|
|
||||||
|
Contributing authors:
|
||||||
|
Thomas Lichtenegger, Sanaz Abbasi
|
||||||
|
Copyright (C) 2015- Johannes Kepler University, Linz
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of CFDEMcoupling academic.
|
||||||
|
|
||||||
|
CFDEMcoupling academic 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.
|
||||||
|
|
||||||
|
CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef terminalVelocity_H
|
||||||
|
#define terminalVelocity_H
|
||||||
|
|
||||||
|
#include "forceModel.H"
|
||||||
|
#include "interpolationCellPoint.H"
|
||||||
|
#include "cellSet.H"
|
||||||
|
//#include "recBase.H"
|
||||||
|
//#include "recModel.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class freeStreaming Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class terminalVelocity
|
||||||
|
:
|
||||||
|
public forceModel
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
dictionary propsDict_;
|
||||||
|
|
||||||
|
bool interpolate_;
|
||||||
|
|
||||||
|
const fvMesh& mesh_;
|
||||||
|
|
||||||
|
// ignore streaming velocity in region
|
||||||
|
word ignoreCellsName_;
|
||||||
|
|
||||||
|
autoPtr<cellSet> ignoreCells_;
|
||||||
|
|
||||||
|
bool existIgnoreCells_;
|
||||||
|
|
||||||
|
// word turbDissipationRateFieldName_;
|
||||||
|
|
||||||
|
// word turbKineticEnergyFieldName_;
|
||||||
|
|
||||||
|
// word recurrenceBaseName_;
|
||||||
|
|
||||||
|
// volScalarField* turbKineticEnergy_;
|
||||||
|
|
||||||
|
bool existturbDissipationRateInObjReg_;
|
||||||
|
|
||||||
|
bool turbulenceCorrection_;
|
||||||
|
|
||||||
|
volScalarField* turbDissipationRate_;
|
||||||
|
|
||||||
|
// mutable volScalarField delta;
|
||||||
|
|
||||||
|
volScalarField wallIndicatorField_;
|
||||||
|
|
||||||
|
scalar liquidViscosity_;
|
||||||
|
|
||||||
|
// drag reduction factor in turbulent flow
|
||||||
|
scalar dragReductionFactor_;
|
||||||
|
|
||||||
|
// terminal rising velocity of the bubble in the resting liquid
|
||||||
|
mutable vector terminalVel_;
|
||||||
|
|
||||||
|
word gravityFieldName_;
|
||||||
|
|
||||||
|
const uniformDimensionedVectorField& g_; // ref to gravity
|
||||||
|
|
||||||
|
bool ignoreCell(label) const;
|
||||||
|
|
||||||
|
void updateEpsilon() const;
|
||||||
|
|
||||||
|
// recBase* recurrenceBase_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("terminalVelocity");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
terminalVelocity
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
cfdemCloud& sm
|
||||||
|
);
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
|
||||||
|
~terminalVelocity();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
void setForce() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -62,6 +62,24 @@ turbulentDispersion::turbulentDispersion
|
|||||||
ignoreCellsName_(propsDict_.lookupOrDefault<word>("ignoreCellsName","none")),
|
ignoreCellsName_(propsDict_.lookupOrDefault<word>("ignoreCellsName","none")),
|
||||||
ignoreCells_(),
|
ignoreCells_(),
|
||||||
existIgnoreCells_(true),
|
existIgnoreCells_(true),
|
||||||
|
usePreCalcNut_(propsDict_.lookupOrDefault<bool>("usePreCalcNut",false)),
|
||||||
|
nutName_(propsDict_.lookupOrDefault<word>("nutName","nut")),
|
||||||
|
usePreCalcK_(propsDict_.lookupOrDefault<bool>("usePreCalcK",false)),
|
||||||
|
kName_(propsDict_.lookupOrDefault<word>("kName","k")),
|
||||||
|
usePreCalcDispField_(propsDict_.lookupOrDefault<bool>("usePreCalcDispField",false)),
|
||||||
|
dispFieldName_(propsDict_.lookupOrDefault<word>("dispFieldName","dispVarField")),
|
||||||
|
nut_
|
||||||
|
( IOobject
|
||||||
|
(
|
||||||
|
"nuTurb",
|
||||||
|
sm.mesh().time().timeName(),
|
||||||
|
sm.mesh(),
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
sm.mesh(),
|
||||||
|
dimensionedScalar("zero", dimensionSet(0,2,-1,0,0,0,0), 0.0)
|
||||||
|
),
|
||||||
wallIndicatorField_
|
wallIndicatorField_
|
||||||
( IOobject
|
( IOobject
|
||||||
(
|
(
|
||||||
@ -74,13 +92,23 @@ turbulentDispersion::turbulentDispersion
|
|||||||
sm.mesh(),
|
sm.mesh(),
|
||||||
dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0)
|
dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0)
|
||||||
),
|
),
|
||||||
minTurbKineticEnergy_(propsDict_.lookupOrDefault<scalar>("minTurbKineticEnergy", 0.0)),
|
delta_
|
||||||
turbKineticEnergyFieldName_(propsDict_.lookupOrDefault<word>("turbKineticEnergyFieldName","")),
|
( IOobject
|
||||||
turbKineticEnergy_(NULL),
|
(
|
||||||
existTurbKineticEnergyInObjReg_(false),
|
"delta",
|
||||||
|
sm.mesh().time().timeName(),
|
||||||
|
sm.mesh(),
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
sm.mesh(),
|
||||||
|
dimensionedScalar("delta", dimLength, 1.0)
|
||||||
|
),
|
||||||
|
turbulentSchmidtNumber_(readScalar(propsDict_.lookup("turbulentSchmidtNumber"))),
|
||||||
voidfractionFieldName_(propsDict_.lookupOrDefault<word>("voidfractionFieldName","voidfraction")),
|
voidfractionFieldName_(propsDict_.lookupOrDefault<word>("voidfractionFieldName","voidfraction")),
|
||||||
voidfraction_(sm.mesh().lookupObject<volScalarField> (voidfractionFieldName_)),
|
voidfraction_(sm.mesh().lookupObject<volScalarField> (voidfractionFieldName_)),
|
||||||
critVoidfraction_(propsDict_.lookupOrDefault<scalar>("critVoidfraction", 0.9)),
|
critVoidfraction_(propsDict_.lookupOrDefault<scalar>("critVoidfraction", 0.9)),
|
||||||
|
Ck_(propsDict_.lookupOrDefault<scalar>("turbKineticEnergyCoeff", 0.094)),
|
||||||
ranGen_(clock::getTime()+pid())
|
ranGen_(clock::getTime()+pid())
|
||||||
{
|
{
|
||||||
if (ignoreCellsName_ != "none")
|
if (ignoreCellsName_ != "none")
|
||||||
@ -91,6 +119,16 @@ turbulentDispersion::turbulentDispersion
|
|||||||
}
|
}
|
||||||
else existIgnoreCells_ = false;
|
else existIgnoreCells_ = false;
|
||||||
|
|
||||||
|
if ((usePreCalcNut_ && usePreCalcK_) || (usePreCalcNut_ && usePreCalcDispField_) || (usePreCalcDispField_ && usePreCalcK_))
|
||||||
|
{
|
||||||
|
FatalError<< "Cannot use more than one precalculated nut, k and displacement fluctuations at the same time. Choose one." << abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usePreCalcK_)
|
||||||
|
{
|
||||||
|
delta_.primitiveFieldRef()=Foam::pow(mesh_.V(),1.0/3.0);
|
||||||
|
}
|
||||||
|
|
||||||
// define a field to indicate if a cell is next to boundary
|
// define a field to indicate if a cell is next to boundary
|
||||||
label cellI = -1;
|
label cellI = -1;
|
||||||
forAll (mesh_.boundary(),patchI)
|
forAll (mesh_.boundary(),patchI)
|
||||||
@ -105,45 +143,18 @@ turbulentDispersion::turbulentDispersion
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (turbKineticEnergyFieldName_ != "")
|
scalar dtCFD = voidfraction_.mesh().time().deltaTValue();
|
||||||
{
|
scalar dtDEM = particleCloud_.dataExchangeM().DEMts();
|
||||||
existTurbKineticEnergyInObjReg_ = true;
|
// if CFD step is larger than DEM step, a corresponding number of DEM steps is taken to reach the CFD step;
|
||||||
volScalarField& k(const_cast<volScalarField&>(sm.mesh().lookupObject<volScalarField> (turbKineticEnergyFieldName_)));
|
// if DEM step is larger than CFD step, no update occurs so that full DEM step needs to be taken
|
||||||
turbKineticEnergy_ = &k;
|
dt_ = max(dtCFD, dtDEM);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
turbKineticEnergy_ = new volScalarField
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"turbKinEnergy",
|
|
||||||
mesh_.time().timeName(),
|
|
||||||
mesh_,
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
mesh_,
|
|
||||||
dimensionedScalar("zero", dimensionSet(0,2,-2,0,0), 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure this is the last force model in list so that fluid velocity does not get overwritten
|
|
||||||
label numLastForceModel = sm.nrForceModels();
|
|
||||||
word lastForceModel = sm.forceModels()[numLastForceModel-1];
|
|
||||||
if (lastForceModel != "turbulentDispersion")
|
|
||||||
{
|
|
||||||
FatalError <<"Force model 'turbulentDispersion' needs to be last in list!\n" << abort(FatalError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
turbulentDispersion::~turbulentDispersion()
|
turbulentDispersion::~turbulentDispersion()
|
||||||
{
|
{}
|
||||||
if (!existTurbKineticEnergyInObjReg_) delete turbKineticEnergy_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -157,45 +168,72 @@ bool turbulentDispersion::ignoreCell(label cell) const
|
|||||||
|
|
||||||
void turbulentDispersion::setForce() const
|
void turbulentDispersion::setForce() const
|
||||||
{
|
{
|
||||||
if (!existTurbKineticEnergyInObjReg_)
|
if (!usePreCalcNut_ && !usePreCalcK_ && !usePreCalcDispField_)
|
||||||
{
|
{
|
||||||
*turbKineticEnergy_ = particleCloud_.turbulence().k()();
|
nut_ = particleCloud_.turbulence().nut()();
|
||||||
|
}
|
||||||
|
else if (usePreCalcNut_)
|
||||||
|
{
|
||||||
|
volScalarField& nutRef (const_cast<volScalarField&>(mesh_.lookupObject<volScalarField> (nutName_)));
|
||||||
|
nut_ = nutRef;
|
||||||
|
}
|
||||||
|
else if (usePreCalcK_)
|
||||||
|
{
|
||||||
|
volScalarField& kRef (const_cast<volScalarField&>(mesh_.lookupObject<volScalarField> (kName_)));
|
||||||
|
nut_ = Ck_ * delta_ * sqrt(kRef);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
volVectorField& dispFieldRef (const_cast<volVectorField&>(mesh_.lookupObject<volVectorField> (dispFieldName_)));
|
||||||
|
dispField_ = &dispFieldRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
label cellI = -1;
|
label cellI = -1;
|
||||||
label patchID = -1;
|
label patchID = -1;
|
||||||
label faceIGlobal = -1;
|
label faceIGlobal = -1;
|
||||||
scalar flucProjection = 0.0;
|
scalar flucProjection = 0.0;
|
||||||
scalar k = 0.0;
|
scalar D = 0.0;
|
||||||
|
scalar randScalar = 0.0;
|
||||||
vector faceINormal = vector::zero;
|
vector faceINormal = vector::zero;
|
||||||
vector flucU = vector::zero;
|
vector flucU = vector::zero;
|
||||||
vector position = vector::zero;
|
vector position = vector::zero;
|
||||||
word patchName("");
|
word patchName("");
|
||||||
|
|
||||||
interpolationCellPoint<scalar> turbKineticEnergyInterpolator_(*turbKineticEnergy_);
|
interpolationCellPoint<scalar> nutInterpolator_(nut_);
|
||||||
|
|
||||||
for(int index = 0;index < particleCloud_.numberOfParticles(); ++index)
|
for(int index = 0; index < particleCloud_.numberOfParticles(); ++index)
|
||||||
{
|
{
|
||||||
cellI = particleCloud_.cellIDs()[index][0];
|
cellI = particleCloud_.cellIDs()[index][0];
|
||||||
if (cellI > -1 && !ignoreCell(cellI))
|
if (cellI > -1 && !ignoreCell(cellI))
|
||||||
{
|
{
|
||||||
// particles in dilute regions follow fluid without fluctuations
|
if (usePreCalcDispField_)
|
||||||
|
{
|
||||||
if (voidfraction_[cellI] < critVoidfraction_)
|
for (label comp=0; comp<3; comp++)
|
||||||
|
{
|
||||||
|
#if OPENFOAM_VERSION_MAJOR < 6
|
||||||
|
randScalar = ranGen_.GaussNormal();
|
||||||
|
#else
|
||||||
|
randScalar = ranGen_.scalarNormal();
|
||||||
|
#endif
|
||||||
|
flucU.component(comp) = randScalar * (*dispField_)[cellI].component(comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (interpolate_)
|
if (interpolate_)
|
||||||
{
|
{
|
||||||
position = particleCloud_.position(index);
|
position = particleCloud_.position(index);
|
||||||
k = turbKineticEnergyInterpolator_.interpolate(position,cellI);
|
D = nutInterpolator_.interpolate(position,cellI) / turbulentSchmidtNumber_;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
k = (*turbKineticEnergy_)[cellI];
|
D = nut_[cellI] / turbulentSchmidtNumber_;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k < minTurbKineticEnergy_) k = minTurbKineticEnergy_;
|
// include concentration dependence on the diffusivity at this point if necessary
|
||||||
|
|
||||||
flucU=unitFlucDir()*Foam::sqrt(2.0*k);
|
flucU=unitFlucDir()*Foam::sqrt(6.0*D/dt_);
|
||||||
|
}
|
||||||
|
|
||||||
// prevent particles being pushed through walls by regulating velocity fluctuations
|
// prevent particles being pushed through walls by regulating velocity fluctuations
|
||||||
// check if cell is adjacent to wall and remove corresponding components
|
// check if cell is adjacent to wall and remove corresponding components
|
||||||
@ -220,8 +258,7 @@ void turbulentDispersion::setForce() const
|
|||||||
|
|
||||||
for(int j=0;j<3;j++)
|
for(int j=0;j<3;j++)
|
||||||
{
|
{
|
||||||
particleCloud_.fluidVels()[index][j] += flucU[j];
|
particleCloud_.particleFlucVels()[index][j] += flucU[j];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,15 +58,29 @@ protected:
|
|||||||
|
|
||||||
bool existIgnoreCells_;
|
bool existIgnoreCells_;
|
||||||
|
|
||||||
mutable volScalarField wallIndicatorField_;
|
bool usePreCalcNut_;
|
||||||
|
|
||||||
scalar minTurbKineticEnergy_;
|
word nutName_;
|
||||||
|
|
||||||
word turbKineticEnergyFieldName_;
|
bool usePreCalcK_;
|
||||||
|
|
||||||
volScalarField* turbKineticEnergy_;
|
word kName_;
|
||||||
|
|
||||||
bool existTurbKineticEnergyInObjReg_;
|
bool usePreCalcDispField_;
|
||||||
|
|
||||||
|
word dispFieldName_;
|
||||||
|
|
||||||
|
mutable volVectorField* dispField_;
|
||||||
|
|
||||||
|
mutable volScalarField nut_;
|
||||||
|
|
||||||
|
volScalarField wallIndicatorField_;
|
||||||
|
|
||||||
|
volScalarField delta_;
|
||||||
|
|
||||||
|
scalar dt_;
|
||||||
|
|
||||||
|
scalar turbulentSchmidtNumber_;
|
||||||
|
|
||||||
word voidfractionFieldName_;
|
word voidfractionFieldName_;
|
||||||
|
|
||||||
@ -74,10 +88,12 @@ protected:
|
|||||||
|
|
||||||
scalar critVoidfraction_;
|
scalar critVoidfraction_;
|
||||||
|
|
||||||
virtual vector unitFlucDir() const;
|
scalar Ck_;
|
||||||
|
|
||||||
mutable Random ranGen_;
|
mutable Random ranGen_;
|
||||||
|
|
||||||
|
virtual vector unitFlucDir() const;
|
||||||
|
|
||||||
bool ignoreCell(label) const;
|
bool ignoreCell(label) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -0,0 +1,256 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
CFDEMcoupling academic - Open Source CFD-DEM coupling
|
||||||
|
|
||||||
|
Contributing authors:
|
||||||
|
Thomas Lichtenegger
|
||||||
|
Copyright (C) 2015- Johannes Kepler University, Linz
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of CFDEMcoupling academic.
|
||||||
|
|
||||||
|
CFDEMcoupling academic 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.
|
||||||
|
|
||||||
|
CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "error.H"
|
||||||
|
|
||||||
|
#include "turbulentVelocityFluctuations.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "OFstream.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(turbulentVelocityFluctuations, 0);
|
||||||
|
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
forceModel,
|
||||||
|
turbulentVelocityFluctuations,
|
||||||
|
dictionary
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Construct from components
|
||||||
|
turbulentVelocityFluctuations::turbulentVelocityFluctuations
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
cfdemCloud& sm,
|
||||||
|
word type
|
||||||
|
)
|
||||||
|
:
|
||||||
|
forceModel(dict,sm),
|
||||||
|
propsDict_(dict.subDict(type + "Props")),
|
||||||
|
interpolate_(propsDict_.lookupOrDefault<bool>("interpolation", false)),
|
||||||
|
mesh_(sm.mesh()),
|
||||||
|
ignoreCellsName_(propsDict_.lookupOrDefault<word>("ignoreCellsName","none")),
|
||||||
|
ignoreCells_(),
|
||||||
|
existIgnoreCells_(true),
|
||||||
|
wallIndicatorField_
|
||||||
|
( IOobject
|
||||||
|
(
|
||||||
|
"wallIndicator",
|
||||||
|
sm.mesh().time().timeName(),
|
||||||
|
sm.mesh(),
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
sm.mesh(),
|
||||||
|
dimensionedScalar("zero", dimensionSet(0,0,0,0,0,0,0), 0.0)
|
||||||
|
),
|
||||||
|
minTurbKineticEnergy_(propsDict_.lookupOrDefault<scalar>("minTurbKineticEnergy", 0.0)),
|
||||||
|
turbKineticEnergyFieldName_(propsDict_.lookupOrDefault<word>("turbKineticEnergyFieldName","")),
|
||||||
|
turbKineticEnergy_(NULL),
|
||||||
|
existTurbKineticEnergyInObjReg_(false),
|
||||||
|
voidfractionFieldName_(propsDict_.lookupOrDefault<word>("voidfractionFieldName","voidfraction")),
|
||||||
|
voidfraction_(sm.mesh().lookupObject<volScalarField> (voidfractionFieldName_)),
|
||||||
|
critVoidfraction_(propsDict_.lookupOrDefault<scalar>("critVoidfraction", 0.9)),
|
||||||
|
ranGen_(clock::getTime()+pid())
|
||||||
|
{
|
||||||
|
if (ignoreCellsName_ != "none")
|
||||||
|
{
|
||||||
|
ignoreCells_.set(new cellSet(particleCloud_.mesh(),ignoreCellsName_));
|
||||||
|
Info << type << ": ignoring fluctuations in cellSet " << ignoreCells_().name() <<
|
||||||
|
" with " << ignoreCells_().size() << " cells." << endl;
|
||||||
|
}
|
||||||
|
else existIgnoreCells_ = false;
|
||||||
|
|
||||||
|
// define a field to indicate if a cell is next to boundary
|
||||||
|
label cellI = -1;
|
||||||
|
forAll (mesh_.boundary(),patchI)
|
||||||
|
{
|
||||||
|
word patchName = mesh_.boundary()[patchI].name();
|
||||||
|
if (patchName.rfind("procB",0) == 0) continue;
|
||||||
|
|
||||||
|
forAll(mesh_.boundary()[patchI], faceI)
|
||||||
|
{
|
||||||
|
cellI = mesh_.boundary()[patchI].faceCells()[faceI];
|
||||||
|
wallIndicatorField_[cellI] = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (turbKineticEnergyFieldName_ != "")
|
||||||
|
{
|
||||||
|
existTurbKineticEnergyInObjReg_ = true;
|
||||||
|
volScalarField& k(const_cast<volScalarField&>(sm.mesh().lookupObject<volScalarField> (turbKineticEnergyFieldName_)));
|
||||||
|
turbKineticEnergy_ = &k;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
turbKineticEnergy_ = new volScalarField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"turbKinEnergy",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensionedScalar("zero", dimensionSet(0,2,-2,0,0), 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure this is the last force model in list so that fluid velocity does not get overwritten
|
||||||
|
label numLastForceModel = sm.nrForceModels();
|
||||||
|
word lastForceModel = sm.forceModels()[numLastForceModel-1];
|
||||||
|
if (lastForceModel != "turbulentVelocityFluctuations")
|
||||||
|
{
|
||||||
|
FatalError <<"Force model 'turbulentVelocityFluctuations' needs to be last in list!\n" << abort(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
turbulentVelocityFluctuations::~turbulentVelocityFluctuations()
|
||||||
|
{
|
||||||
|
if (!existTurbKineticEnergyInObjReg_) delete turbKineticEnergy_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * private Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool turbulentVelocityFluctuations::ignoreCell(label cell) const
|
||||||
|
{
|
||||||
|
if (!existIgnoreCells_) return false;
|
||||||
|
else return ignoreCells_()[cell];
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void turbulentVelocityFluctuations::setForce() const
|
||||||
|
{
|
||||||
|
if (!existTurbKineticEnergyInObjReg_)
|
||||||
|
{
|
||||||
|
*turbKineticEnergy_ = particleCloud_.turbulence().k()();
|
||||||
|
}
|
||||||
|
|
||||||
|
label cellI = -1;
|
||||||
|
label patchID = -1;
|
||||||
|
label faceIGlobal = -1;
|
||||||
|
scalar flucProjection = 0.0;
|
||||||
|
scalar k = 0.0;
|
||||||
|
vector faceINormal = vector::zero;
|
||||||
|
vector flucU = vector::zero;
|
||||||
|
vector position = vector::zero;
|
||||||
|
word patchName("");
|
||||||
|
|
||||||
|
interpolationCellPoint<scalar> turbKineticEnergyInterpolator_(*turbKineticEnergy_);
|
||||||
|
|
||||||
|
for(int index = 0;index < particleCloud_.numberOfParticles(); ++index)
|
||||||
|
{
|
||||||
|
cellI = particleCloud_.cellIDs()[index][0];
|
||||||
|
if (cellI > -1 && !ignoreCell(cellI))
|
||||||
|
{
|
||||||
|
// particles in dilute regions follow fluid without fluctuations
|
||||||
|
|
||||||
|
if (voidfraction_[cellI] < critVoidfraction_)
|
||||||
|
{
|
||||||
|
if (interpolate_)
|
||||||
|
{
|
||||||
|
position = particleCloud_.position(index);
|
||||||
|
k = turbKineticEnergyInterpolator_.interpolate(position,cellI);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
k = (*turbKineticEnergy_)[cellI];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k < minTurbKineticEnergy_) k = minTurbKineticEnergy_;
|
||||||
|
|
||||||
|
flucU=unitFlucDir()*Foam::sqrt(2.0*k);
|
||||||
|
|
||||||
|
// prevent particles being pushed through walls by regulating velocity fluctuations
|
||||||
|
// check if cell is adjacent to wall and remove corresponding components
|
||||||
|
if (wallIndicatorField_[cellI] > 0.5)
|
||||||
|
{
|
||||||
|
const cell& faces = mesh_.cells()[cellI];
|
||||||
|
forAll (faces, faceI)
|
||||||
|
{
|
||||||
|
faceIGlobal = faces[faceI];
|
||||||
|
patchID = mesh_.boundaryMesh().whichPatch(faceIGlobal);
|
||||||
|
if (patchID < 0) continue;
|
||||||
|
patchName = mesh_.boundary()[patchID].name();
|
||||||
|
|
||||||
|
if (patchName.rfind("procB",0) == 0) continue;
|
||||||
|
|
||||||
|
faceINormal = mesh_.Sf()[faceIGlobal];
|
||||||
|
faceINormal /= mag(faceINormal);
|
||||||
|
flucProjection = faceINormal&flucU;
|
||||||
|
if (flucProjection > 0.0) flucU -= flucProjection*faceINormal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j=0;j<3;j++)
|
||||||
|
{
|
||||||
|
particleCloud_.fluidVels()[index][j] += flucU[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vector turbulentVelocityFluctuations::unitFlucDir() const
|
||||||
|
{
|
||||||
|
// unit random vector
|
||||||
|
// algorithm according to:
|
||||||
|
// Marsaglia. "Choosing a point from the surface of a sphere." The Annals of Mathematical Statistics 43.2 (1972): 645-646.
|
||||||
|
scalar v1(0.0);
|
||||||
|
scalar v2(0.0);
|
||||||
|
scalar s(10.0);
|
||||||
|
scalar s2(0.0);
|
||||||
|
vector rvec(0,0,0);
|
||||||
|
while(s>1.0)
|
||||||
|
{
|
||||||
|
v1=2*(ranGen_.scalar01()-0.5);
|
||||||
|
v2=2*(ranGen_.scalar01()-0.5);
|
||||||
|
s=v1*v1+v2*v2;
|
||||||
|
}
|
||||||
|
s2=Foam::sqrt(1-s);
|
||||||
|
rvec[0]=2*v1*s2;
|
||||||
|
rvec[1]=2*v2*s2;
|
||||||
|
rvec[2]=1-2*s;
|
||||||
|
return rvec;
|
||||||
|
}
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,117 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
CFDEMcoupling academic - Open Source CFD-DEM coupling
|
||||||
|
|
||||||
|
Contributing authors:
|
||||||
|
Thomas Lichtenegger
|
||||||
|
Copyright (C) 2015- Johannes Kepler University, Linz
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of CFDEMcoupling academic.
|
||||||
|
|
||||||
|
CFDEMcoupling academic 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.
|
||||||
|
|
||||||
|
CFDEMcoupling academic 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 CFDEMcoupling academic. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef turbulentVelocityFluctuations_H
|
||||||
|
#define turbulentVelocityFluctuations_H
|
||||||
|
|
||||||
|
#include "forceModel.H"
|
||||||
|
#include "interpolationCellPoint.H"
|
||||||
|
#include "Random.H"
|
||||||
|
#include "autoPtr.H"
|
||||||
|
#include "cellSet.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class turbulentVelocityFluctuations Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class turbulentVelocityFluctuations
|
||||||
|
:
|
||||||
|
public forceModel
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
dictionary propsDict_;
|
||||||
|
|
||||||
|
bool interpolate_;
|
||||||
|
|
||||||
|
const fvMesh& mesh_;
|
||||||
|
|
||||||
|
// ignore fluctuations in region
|
||||||
|
word ignoreCellsName_;
|
||||||
|
|
||||||
|
autoPtr<cellSet> ignoreCells_;
|
||||||
|
|
||||||
|
bool existIgnoreCells_;
|
||||||
|
|
||||||
|
volScalarField wallIndicatorField_;
|
||||||
|
|
||||||
|
scalar minTurbKineticEnergy_;
|
||||||
|
|
||||||
|
word turbKineticEnergyFieldName_;
|
||||||
|
|
||||||
|
volScalarField* turbKineticEnergy_;
|
||||||
|
|
||||||
|
bool existTurbKineticEnergyInObjReg_;
|
||||||
|
|
||||||
|
word voidfractionFieldName_;
|
||||||
|
|
||||||
|
const volScalarField& voidfraction_;
|
||||||
|
|
||||||
|
scalar critVoidfraction_;
|
||||||
|
|
||||||
|
virtual vector unitFlucDir() const;
|
||||||
|
|
||||||
|
mutable Random ranGen_;
|
||||||
|
|
||||||
|
bool ignoreCell(label) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("turbulentVelocityFluctuations");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
turbulentVelocityFluctuations
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
cfdemCloud& sm,
|
||||||
|
word type = "turbulentVelocityFluctuations"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
|
||||||
|
~turbulentVelocityFluctuations();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
void setForce() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -54,7 +54,34 @@ deactivateCouple::deactivateCouple
|
|||||||
cfdemCloud& sm
|
cfdemCloud& sm
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
momCoupleModel(dict,sm)
|
momCoupleModel(dict,sm),
|
||||||
|
fEmpty_
|
||||||
|
( IOobject
|
||||||
|
(
|
||||||
|
"fEmpty",
|
||||||
|
sm.mesh().time().timeName(),
|
||||||
|
sm.mesh(),
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
sm.mesh(),
|
||||||
|
dimensionedVector("zero", dimensionSet(1,-2,-2,0,0), vector::zero),
|
||||||
|
"zeroGradient"
|
||||||
|
),
|
||||||
|
KslEmpty_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"KslEmpty",
|
||||||
|
sm.mesh().time().timeName(),
|
||||||
|
sm.mesh(),
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
sm.mesh(),
|
||||||
|
dimensionedScalar("zero", dimensionSet(1,-3,-1,0,0), 0),
|
||||||
|
"zeroGradient"
|
||||||
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
@ -65,9 +92,21 @@ deactivateCouple::~deactivateCouple()
|
|||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
void Foam::deactivateCouple::resetMomSourceField()
|
void deactivateCouple::resetMomSourceField()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
tmp<volVectorField> deactivateCouple::expMomSource()
|
||||||
|
{
|
||||||
|
tmp<volVectorField> tsource(fEmpty_);
|
||||||
|
return tsource;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp<volScalarField> deactivateCouple::impMomSource()
|
||||||
|
{
|
||||||
|
tmp<volScalarField> tsource(KslEmpty_);
|
||||||
|
return tsource;
|
||||||
|
|
||||||
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|||||||
@ -42,6 +42,9 @@ class deactivateCouple
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
volVectorField fEmpty_;
|
||||||
|
|
||||||
|
volScalarField KslEmpty_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -65,6 +68,10 @@ public:
|
|||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
void resetMomSourceField();
|
void resetMomSourceField();
|
||||||
|
|
||||||
|
tmp<volVectorField> expMomSource();
|
||||||
|
|
||||||
|
tmp<volScalarField> impMomSource();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,8 @@ gravity::gravity
|
|||||||
voidfraction_(sm.mesh().lookupObject<volScalarField> (voidfractionFieldName_)),
|
voidfraction_(sm.mesh().lookupObject<volScalarField> (voidfractionFieldName_)),
|
||||||
rhoGFieldName_(propsDict_.lookupOrDefault<word>("rhoGFieldName","rho")),
|
rhoGFieldName_(propsDict_.lookupOrDefault<word>("rhoGFieldName","rho")),
|
||||||
rhoG_(sm.mesh().lookupObject<volScalarField> (rhoGFieldName_)),
|
rhoG_(sm.mesh().lookupObject<volScalarField> (rhoGFieldName_)),
|
||||||
g_("g",dimensionSet(0,1,-2,0,0),vector(0,0,-9.81))
|
gravityFieldName_(propsDict_.lookupOrDefault<word>("gravityFieldName","g")),
|
||||||
|
g_(sm.mesh().lookupObject<uniformDimensionedVectorField> (gravityFieldName_))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -54,7 +54,9 @@ protected:
|
|||||||
|
|
||||||
const volScalarField& rhoG_;
|
const volScalarField& rhoG_;
|
||||||
|
|
||||||
const dimensionedVector g_;
|
word gravityFieldName_;
|
||||||
|
|
||||||
|
const uniformDimensionedVectorField& g_; // ref to gravity
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,96 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
License
|
||||||
|
This 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.
|
||||||
|
This code 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 this code. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "error.H"
|
||||||
|
#include "secondaryPhaseInducedBuoyancy.H"
|
||||||
|
#include "mathExtra.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(secondaryPhaseInducedBuoyancy, 0);
|
||||||
|
|
||||||
|
addToRunTimeSelectionTable(otherForceModel, secondaryPhaseInducedBuoyancy, dictionary);
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// Construct from components
|
||||||
|
secondaryPhaseInducedBuoyancy::secondaryPhaseInducedBuoyancy
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
cfdemCloud& sm
|
||||||
|
)
|
||||||
|
:
|
||||||
|
otherForceModel(dict,sm),
|
||||||
|
propsDict_(dict.subDict(typeName + "Props")),
|
||||||
|
voidfractionFieldName_(propsDict_.lookupOrDefault<word>("voidfractionFieldName","voidfraction")),
|
||||||
|
voidfraction_(sm.mesh().lookupObject<volScalarField> (voidfractionFieldName_)),
|
||||||
|
diffRho_("diffRho",dimensionSet(1,-3,0,0,0),0.0),
|
||||||
|
gravityFieldName_(propsDict_.lookupOrDefault<word>("gravityFieldName","g")),
|
||||||
|
g_(sm.mesh().lookupObject<uniformDimensionedVectorField> (gravityFieldName_))
|
||||||
|
{
|
||||||
|
// density difference of fluid and secondary phase
|
||||||
|
diffRho_.value()=readScalar(propsDict_.lookup ("diffRho"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
secondaryPhaseInducedBuoyancy::~secondaryPhaseInducedBuoyancy()
|
||||||
|
{}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
tmp<volVectorField> secondaryPhaseInducedBuoyancy::exportForceField()
|
||||||
|
{
|
||||||
|
tmp<volVectorField> tsource
|
||||||
|
(
|
||||||
|
new volVectorField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"secondaryPhaseInducedBuoyancy",
|
||||||
|
particleCloud_.mesh().time().timeName(),
|
||||||
|
particleCloud_.mesh(),
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
particleCloud_.mesh(),
|
||||||
|
dimensionedVector
|
||||||
|
(
|
||||||
|
"zero",dimensionSet(1, -2, -2, 0, 0),vector::zero
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
volVectorField& source = tsource.ref();
|
||||||
|
|
||||||
|
source = diffRho_ * (1.0-voidfraction_) * g_;
|
||||||
|
|
||||||
|
return tsource;
|
||||||
|
}
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
License
|
||||||
|
This 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.
|
||||||
|
This code 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 this code. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Copyright (C) 2015- Thomas Lichtenegger, JKU Linz, Austria
|
||||||
|
|
||||||
|
|
||||||
|
Class
|
||||||
|
secondaryPhaseInducedBuoyancy
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
secondaryPhaseInducedBuoyancy.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef secondaryPhaseInducedBuoyancy_H
|
||||||
|
#define secondaryPhaseInducedBuoyancy_H
|
||||||
|
|
||||||
|
#include "otherForceModel.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class secondaryPhaseInducedBuoyancy Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class secondaryPhaseInducedBuoyancy
|
||||||
|
:
|
||||||
|
public otherForceModel
|
||||||
|
{
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
dictionary propsDict_;
|
||||||
|
|
||||||
|
word voidfractionFieldName_;
|
||||||
|
|
||||||
|
const volScalarField& voidfraction_;
|
||||||
|
|
||||||
|
// density dispersed phase - density continuous phase
|
||||||
|
dimensionedScalar diffRho_;
|
||||||
|
|
||||||
|
word gravityFieldName_;
|
||||||
|
|
||||||
|
const uniformDimensionedVectorField& g_; // ref to gravity
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("secondaryPhaseInducedBuoyancy");
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
secondaryPhaseInducedBuoyancy
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
cfdemCloud& sm
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Destructor
|
||||||
|
|
||||||
|
virtual ~secondaryPhaseInducedBuoyancy();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
|
||||||
|
tmp<volVectorField> exportForceField();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -46,7 +46,9 @@ weightSecondaryPhase::weightSecondaryPhase
|
|||||||
volfracFieldName_(propsDict_.lookup("volfracFieldName")),
|
volfracFieldName_(propsDict_.lookup("volfracFieldName")),
|
||||||
alpha_(sm.mesh().lookupObject<volScalarField> (volfracFieldName_)),
|
alpha_(sm.mesh().lookupObject<volScalarField> (volfracFieldName_)),
|
||||||
rho_("rho",dimensionSet(1,-3,0,0,0),0.0),
|
rho_("rho",dimensionSet(1,-3,0,0,0),0.0),
|
||||||
g_("g",dimensionSet(0,1,-2,0,0),vector(0,0,-9.81))
|
gravityFieldName_(propsDict_.lookupOrDefault<word>("gravityFieldName","g")),
|
||||||
|
g_(sm.mesh().lookupObject<uniformDimensionedVectorField> (gravityFieldName_))
|
||||||
|
|
||||||
{
|
{
|
||||||
if (propsDict_.found("rho"))
|
if (propsDict_.found("rho"))
|
||||||
rho_.value()=readScalar(propsDict_.lookup ("rho"));
|
rho_.value()=readScalar(propsDict_.lookup ("rho"));
|
||||||
|
|||||||
@ -52,7 +52,9 @@ protected:
|
|||||||
|
|
||||||
dimensionedScalar rho_;
|
dimensionedScalar rho_;
|
||||||
|
|
||||||
const dimensionedVector g_;
|
word gravityFieldName_;
|
||||||
|
|
||||||
|
const uniformDimensionedVectorField& g_; // ref to gravity
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -35,12 +35,13 @@ $(chemistryModels)/noChemistry/noChemistry.C
|
|||||||
$(chemistryModels)/diffusionCoefficients/diffusionCoefficients.C
|
$(chemistryModels)/diffusionCoefficients/diffusionCoefficients.C
|
||||||
$(chemistryModels)/massTransferCoeff/massTransferCoeff.C
|
$(chemistryModels)/massTransferCoeff/massTransferCoeff.C
|
||||||
$(chemistryModels)/reactantPerParticle/reactantPerParticle.C
|
$(chemistryModels)/reactantPerParticle/reactantPerParticle.C
|
||||||
|
$(chemistryModels)/initMultiLayers/initMultiLayers.C
|
||||||
|
|
||||||
$(energyModels)/energyModel/energyModel.C
|
$(energyModels)/energyModel/energyModel.C
|
||||||
$(energyModels)/energyModel/newEnergyModel.C
|
$(energyModels)/energyModel/newEnergyModel.C
|
||||||
$(energyModels)/heatTransferGunn/heatTransferGunn.C
|
$(energyModels)/heatTransferGunn/heatTransferGunn.C
|
||||||
$(energyModels)/heatTransferRanzMarshall/heatTransferRanzMarshall.C
|
$(energyModels)/heatTransferRanzMarshall/heatTransferRanzMarshall.C
|
||||||
$(energyModels)/heatTransferGranConduction/heatTransferGranConduction.C
|
$(energyModels)/heatTransferInterGrain/heatTransferInterGrain.C
|
||||||
$(energyModels)/reactionHeat/reactionHeat.C
|
$(energyModels)/reactionHeat/reactionHeat.C
|
||||||
|
|
||||||
$(thermCondModels)/thermCondModel/thermCondModel.C
|
$(thermCondModels)/thermCondModel/thermCondModel.C
|
||||||
@ -83,6 +84,7 @@ $(forceModels)/Fines/ErgunStatFines.C
|
|||||||
$(forceModels)/granKineticEnergy/granKineticEnergy.C
|
$(forceModels)/granKineticEnergy/granKineticEnergy.C
|
||||||
$(forceModels)/particleDeformation/particleDeformation.C
|
$(forceModels)/particleDeformation/particleDeformation.C
|
||||||
$(forceModels)/turbulentDispersion/turbulentDispersion.C
|
$(forceModels)/turbulentDispersion/turbulentDispersion.C
|
||||||
|
$(forceModels)/turbulentVelocityFluctuations/turbulentVelocityFluctuations.C
|
||||||
|
|
||||||
$(forceSubModels)/forceSubModel/newForceSubModel.C
|
$(forceSubModels)/forceSubModel/newForceSubModel.C
|
||||||
$(forceSubModels)/forceSubModel/forceSubModel.C
|
$(forceSubModels)/forceSubModel/forceSubModel.C
|
||||||
@ -95,6 +97,7 @@ $(otherForceModels)/otherForceModel/newOtherForceModel.C
|
|||||||
$(otherForceModels)/gravity/gravity.C
|
$(otherForceModels)/gravity/gravity.C
|
||||||
$(otherForceModels)/weightSecondaryPhase/weightSecondaryPhase.C
|
$(otherForceModels)/weightSecondaryPhase/weightSecondaryPhase.C
|
||||||
$(otherForceModels)/expParticleForces/expParticleForces.C
|
$(otherForceModels)/expParticleForces/expParticleForces.C
|
||||||
|
$(otherForceModels)/secondaryPhaseInducedBuoyancy/secondaryPhaseInducedBuoyancy.C
|
||||||
|
|
||||||
$(probeModels)/probeModel/probeModel.C
|
$(probeModels)/probeModel/probeModel.C
|
||||||
$(probeModels)/probeModel/newProbeModel.C
|
$(probeModels)/probeModel/newProbeModel.C
|
||||||
|
|||||||
@ -37,6 +37,18 @@ recBase::recBase
|
|||||||
const fvMesh& mesh
|
const fvMesh& mesh
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
|
regIOobject
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"recurrenceBase",
|
||||||
|
mesh.time().timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
),
|
||||||
mesh_(mesh),
|
mesh_(mesh),
|
||||||
recProperties_
|
recProperties_
|
||||||
(
|
(
|
||||||
@ -83,6 +95,7 @@ recBase::recBase
|
|||||||
),
|
),
|
||||||
couplingSubStep_(recProperties_.lookupOrDefault<label>("couplingSubStep",0))
|
couplingSubStep_(recProperties_.lookupOrDefault<label>("couplingSubStep",0))
|
||||||
{
|
{
|
||||||
|
|
||||||
recModel_ -> readFieldSeries();
|
recModel_ -> readFieldSeries();
|
||||||
if (!recStatAnalysis_->suppressMatrixAndPath())
|
if (!recStatAnalysis_->suppressMatrixAndPath())
|
||||||
{
|
{
|
||||||
@ -98,6 +111,80 @@ recBase::recBase
|
|||||||
recModel_ -> writeRecPath();
|
recModel_ -> writeRecPath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
recBase::recBase
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,const word recDictName_
|
||||||
|
)
|
||||||
|
:
|
||||||
|
regIOobject
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"recurrenceBase",
|
||||||
|
mesh.time().timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
),
|
||||||
|
mesh_(mesh),
|
||||||
|
recProperties_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
recDictName_,
|
||||||
|
mesh_.time().constant(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
)
|
||||||
|
),
|
||||||
|
recModel_
|
||||||
|
(
|
||||||
|
recModel::New
|
||||||
|
(
|
||||||
|
recProperties_,
|
||||||
|
*this
|
||||||
|
)
|
||||||
|
),
|
||||||
|
recNorm_
|
||||||
|
(
|
||||||
|
recNorm::New
|
||||||
|
(
|
||||||
|
recProperties_,
|
||||||
|
*this
|
||||||
|
)
|
||||||
|
),
|
||||||
|
recPath_
|
||||||
|
(
|
||||||
|
recPath::New
|
||||||
|
(
|
||||||
|
recProperties_,
|
||||||
|
*this
|
||||||
|
)
|
||||||
|
),
|
||||||
|
recStatAnalysis_
|
||||||
|
(
|
||||||
|
recStatAnalysis::New
|
||||||
|
(
|
||||||
|
recProperties_,
|
||||||
|
*this
|
||||||
|
)
|
||||||
|
),
|
||||||
|
couplingSubStep_(recProperties_.lookupOrDefault<label>("couplingSubStep",0))
|
||||||
|
{
|
||||||
|
recModel_ -> readFieldSeries();
|
||||||
|
recNorm_ -> computeRecMatrix();
|
||||||
|
recPath_ -> getRecPath();
|
||||||
|
|
||||||
|
recModel_ -> init();
|
||||||
|
|
||||||
|
recModel_ -> writeRecMatrix();
|
||||||
|
recModel_ -> writeRecPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * //
|
||||||
recBase::~recBase()
|
recBase::~recBase()
|
||||||
|
|||||||
@ -46,6 +46,8 @@ class recStatAnalysis;
|
|||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class recBase
|
class recBase
|
||||||
|
:
|
||||||
|
public regIOobject
|
||||||
{
|
{
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -65,6 +67,7 @@ protected:
|
|||||||
// in case of substepping: couple passive quantity at this substep
|
// in case of substepping: couple passive quantity at this substep
|
||||||
label couplingSubStep_;
|
label couplingSubStep_;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
@ -74,6 +77,11 @@ public:
|
|||||||
(
|
(
|
||||||
const fvMesh& mesh
|
const fvMesh& mesh
|
||||||
);
|
);
|
||||||
|
//- Construct from mesh and a list of recProperties
|
||||||
|
recBase
|
||||||
|
(
|
||||||
|
const fvMesh& mesh, const word recDictName_
|
||||||
|
);
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~recBase();
|
virtual ~recBase();
|
||||||
@ -94,6 +102,12 @@ public:
|
|||||||
|
|
||||||
label couplingSubStep() const;
|
label couplingSubStep() const;
|
||||||
|
|
||||||
|
// Dummy function for regIOobject
|
||||||
|
bool writeData(Ostream&) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1058,6 +1058,11 @@ void lruRecModel::exportAveragedVolVectorField(volVectorField& smoothfield, word
|
|||||||
smoothfield /= counter;
|
smoothfield /= counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label lruRecModel::currentTimeIndex() const
|
||||||
|
{
|
||||||
|
return virtualTimeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|||||||
@ -160,6 +160,8 @@ public:
|
|||||||
label numRecFields() const;
|
label numRecFields() const;
|
||||||
label numDataBaseFields() const;
|
label numDataBaseFields() const;
|
||||||
|
|
||||||
|
label currentTimeIndex() const;
|
||||||
|
|
||||||
void updateRecFields();
|
void updateRecFields();
|
||||||
|
|
||||||
void writeRecMatrix() const;
|
void writeRecMatrix() const;
|
||||||
|
|||||||
@ -224,6 +224,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void updateRecFields() = 0;
|
virtual void updateRecFields() = 0;
|
||||||
|
virtual label currentTimeIndex() const = 0;
|
||||||
|
|
||||||
virtual void writeRecMatrix() const = 0;
|
virtual void writeRecMatrix() const = 0;
|
||||||
|
|
||||||
|
|||||||
@ -63,6 +63,7 @@ standardRecModel::standardRecModel
|
|||||||
cumulativeNumRecFields_(),
|
cumulativeNumRecFields_(),
|
||||||
totNumRecFields_(0),
|
totNumRecFields_(0),
|
||||||
storeAveragedFields_(propsDict_.lookupOrDefault<bool>("storeAveragedFields",false)),
|
storeAveragedFields_(propsDict_.lookupOrDefault<bool>("storeAveragedFields",false)),
|
||||||
|
checkTimeStep_(propsDict_.lookupOrDefault<bool>("checkTimeStep",true)),
|
||||||
recurrenceMatrix_(1,scalar(-1.0)),
|
recurrenceMatrix_(1,scalar(-1.0)),
|
||||||
timeIndexList_(),
|
timeIndexList_(),
|
||||||
timeValueList_(),
|
timeValueList_(),
|
||||||
@ -127,7 +128,11 @@ standardRecModel::standardRecModel
|
|||||||
|
|
||||||
// check if time steps in databases are consistent
|
// check if time steps in databases are consistent
|
||||||
// if no initial number of time steps has been specified, create path for full runtime immediately
|
// if no initial number of time steps has been specified, create path for full runtime immediately
|
||||||
|
if(checkTimeStep_)
|
||||||
|
{
|
||||||
recTimeStep_ = checkTimeStep();
|
recTimeStep_ = checkTimeStep();
|
||||||
|
}
|
||||||
|
|
||||||
if(totRecSteps_ < 0)
|
if(totRecSteps_ < 0)
|
||||||
{
|
{
|
||||||
totRecSteps_ = 1 + static_cast<label>( (endTime_-startTime_) / recTimeStep_ );
|
totRecSteps_ = 1 + static_cast<label>( (endTime_-startTime_) / recTimeStep_ );
|
||||||
@ -196,6 +201,24 @@ void standardRecModel::init()
|
|||||||
{
|
{
|
||||||
recModel::init();
|
recModel::init();
|
||||||
|
|
||||||
|
const objectRegistry& objReg = base_.mesh().thisDb();
|
||||||
|
|
||||||
|
for(int j=0; j<volScalarFieldNames_.size(); j++)
|
||||||
|
{
|
||||||
|
objReg.checkIn(volScalarFieldList_[j][virtualTimeIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j=0; j<volVectorFieldNames_.size(); j++)
|
||||||
|
{
|
||||||
|
objReg.checkIn(volVectorFieldList_[j][virtualTimeIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j=0; j<surfaceScalarFieldNames_.size(); j++)
|
||||||
|
{
|
||||||
|
objReg.checkIn(surfaceScalarFieldList_[j][virtualTimeIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for(int i = 0; i < numDataBases_; i++)
|
for(int i = 0; i < numDataBases_; i++)
|
||||||
{
|
{
|
||||||
if (virtualTimeIndex < cumulativeNumRecFields_[i])
|
if (virtualTimeIndex < cumulativeNumRecFields_[i])
|
||||||
@ -699,6 +722,27 @@ label standardRecModel::numDataBaseFields() const
|
|||||||
|
|
||||||
void standardRecModel::updateRecFields()
|
void standardRecModel::updateRecFields()
|
||||||
{
|
{
|
||||||
|
// make fields of upcoming virtualTimeIndex available in object registry
|
||||||
|
const objectRegistry& objReg = base_.mesh().thisDb();
|
||||||
|
|
||||||
|
for(int j=0; j<volScalarFieldNames_.size(); j++)
|
||||||
|
{
|
||||||
|
objReg.checkOut(volScalarFieldList_[j][virtualTimeIndex]);
|
||||||
|
objReg.checkIn(volScalarFieldList_[j][virtualTimeIndexNext]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j=0; j<volVectorFieldNames_.size(); j++)
|
||||||
|
{
|
||||||
|
objReg.checkOut(volVectorFieldList_[j][virtualTimeIndex]);
|
||||||
|
objReg.checkIn(volVectorFieldList_[j][virtualTimeIndexNext]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j=0; j<surfaceScalarFieldNames_.size(); j++)
|
||||||
|
{
|
||||||
|
objReg.checkOut(surfaceScalarFieldList_[j][virtualTimeIndex]);
|
||||||
|
objReg.checkIn(surfaceScalarFieldList_[j][virtualTimeIndexNext]);
|
||||||
|
}
|
||||||
|
|
||||||
virtualTimeIndex = virtualTimeIndexNext;
|
virtualTimeIndex = virtualTimeIndexNext;
|
||||||
virtualTimeIndexNext++;
|
virtualTimeIndexNext++;
|
||||||
|
|
||||||
@ -736,6 +780,10 @@ void standardRecModel::updateRecFields()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label standardRecModel::currentTimeIndex() const
|
||||||
|
{
|
||||||
|
return virtualTimeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
void standardRecModel::writeRecMatrix() const
|
void standardRecModel::writeRecMatrix() const
|
||||||
{
|
{
|
||||||
|
|||||||
@ -61,6 +61,7 @@ protected:
|
|||||||
label totNumRecFields_;
|
label totNumRecFields_;
|
||||||
|
|
||||||
bool storeAveragedFields_;
|
bool storeAveragedFields_;
|
||||||
|
bool checkTimeStep_;
|
||||||
|
|
||||||
// matrix that contains the recurrence ERROR
|
// matrix that contains the recurrence ERROR
|
||||||
SymmetricSquareMatrix<scalar> recurrenceMatrix_;
|
SymmetricSquareMatrix<scalar> recurrenceMatrix_;
|
||||||
@ -151,6 +152,7 @@ public:
|
|||||||
label numDataBaseFields() const;
|
label numDataBaseFields() const;
|
||||||
|
|
||||||
void updateRecFields();
|
void updateRecFields();
|
||||||
|
label currentTimeIndex() const;
|
||||||
|
|
||||||
void writeRecMatrix() const;
|
void writeRecMatrix() const;
|
||||||
|
|
||||||
|
|||||||
@ -56,6 +56,7 @@ MarkovPath::MarkovPath
|
|||||||
:
|
:
|
||||||
recPath(dict, base),
|
recPath(dict, base),
|
||||||
propsDict_(dict.subDict(typeName + "Props")),
|
propsDict_(dict.subDict(typeName + "Props")),
|
||||||
|
searchMinimum_(propsDict_.lookupOrDefault<bool>("searchMinimum",true)),
|
||||||
correlationSteps_(readLabel(propsDict_.lookup("correlationSteps"))),
|
correlationSteps_(readLabel(propsDict_.lookup("correlationSteps"))),
|
||||||
meanIntervalSteps_(propsDict_.lookupOrDefault<label>("meanIntervalSteps",-1)),
|
meanIntervalSteps_(propsDict_.lookupOrDefault<label>("meanIntervalSteps",-1)),
|
||||||
minIntervalSteps_(propsDict_.lookupOrDefault<label>("minIntervalSteps",0)),
|
minIntervalSteps_(propsDict_.lookupOrDefault<label>("minIntervalSteps",0)),
|
||||||
@ -167,7 +168,7 @@ void MarkovPath::extendPath()
|
|||||||
scalar randInterval = ranGen.scalar01();
|
scalar randInterval = ranGen.scalar01();
|
||||||
|
|
||||||
label interval = numIntervals_-1;
|
label interval = numIntervals_-1;
|
||||||
for(int i = numIntervals_-2 ;i >= 0; i--)
|
for(int i = numIntervals_-2; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (randInterval < intervalWeightsCumulative_[i]) interval=i;
|
if (randInterval < intervalWeightsCumulative_[i]) interval=i;
|
||||||
}
|
}
|
||||||
@ -176,6 +177,8 @@ void MarkovPath::extendPath()
|
|||||||
if (interval > 0) startLoop = intervalSizesCumulative_[interval-1];
|
if (interval > 0) startLoop = intervalSizesCumulative_[interval-1];
|
||||||
label endLoop = intervalSizesCumulative_[interval] - meanIntervalSteps_;
|
label endLoop = intervalSizesCumulative_[interval] - meanIntervalSteps_;
|
||||||
|
|
||||||
|
if (searchMinimum_)
|
||||||
|
{
|
||||||
scalar nextMinimum(GREAT);
|
scalar nextMinimum(GREAT);
|
||||||
for (label j = startLoop; j <= endLoop; j++)
|
for (label j = startLoop; j <= endLoop; j++)
|
||||||
{
|
{
|
||||||
@ -186,6 +189,12 @@ void MarkovPath::extendPath()
|
|||||||
seqStart = j+1;
|
seqStart = j+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scalar randIntervalStart = ranGen.scalar01();
|
||||||
|
seqStart = static_cast<label>(startLoop + randIntervalStart*(endLoop - startLoop));
|
||||||
|
}
|
||||||
|
|
||||||
virtualTimeIndex = seqStart;
|
virtualTimeIndex = seqStart;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,6 +59,8 @@ protected:
|
|||||||
|
|
||||||
void weightsNormalization();
|
void weightsNormalization();
|
||||||
|
|
||||||
|
bool searchMinimum_;
|
||||||
|
|
||||||
// correlation steps determine which temporal neighborhood is excluded from nearest-neighbor search
|
// correlation steps determine which temporal neighborhood is excluded from nearest-neighbor search
|
||||||
label correlationSteps_;
|
label correlationSteps_;
|
||||||
|
|
||||||
|
|||||||
46
tutorials/displacementField/CFD/constant/displacementProperties
Executable file
46
tutorials/displacementField/CFD/constant/displacementProperties
Executable file
@ -0,0 +1,46 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
| ========= | |
|
||||||
|
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||||
|
| \\ / O peration | Version: 1.4 |
|
||||||
|
| \\ / A nd | Web: http://www.openfoam.org |
|
||||||
|
| \\/ M anipulation | |
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
FoamFile
|
||||||
|
{
|
||||||
|
version 2.0;
|
||||||
|
format ascii;
|
||||||
|
|
||||||
|
root "";
|
||||||
|
case "";
|
||||||
|
instance "";
|
||||||
|
local "";
|
||||||
|
|
||||||
|
class dictionary;
|
||||||
|
object displacementProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
dumpIndexStart 4004000;
|
||||||
|
|
||||||
|
dumpIndexEnd 4028000;
|
||||||
|
|
||||||
|
dumpIndexDisplacementIncrement 8000;
|
||||||
|
|
||||||
|
dumpIndexInputIncrement 4000;
|
||||||
|
|
||||||
|
nNeighMin 3;
|
||||||
|
|
||||||
|
timePerDisplacementStep 0.1;
|
||||||
|
|
||||||
|
timePerInputStep 0.05;
|
||||||
|
|
||||||
|
startTime 0.0;
|
||||||
|
|
||||||
|
filepath "../DEM/post_disp/dump";
|
||||||
|
|
||||||
|
fillEmptyCells false;
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
74
tutorials/displacementField/CFD/system/blockMeshDict
Normal file
74
tutorials/displacementField/CFD/system/blockMeshDict
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*--------------------------------*- C++ -*----------------------------------*\
|
||||||
|
| ========= | |
|
||||||
|
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
|
||||||
|
| \\ / O peration | Version: 2.3.0 |
|
||||||
|
| \\ / A nd | Web: www.OpenFOAM.org |
|
||||||
|
| \\/ M anipulation | |
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
FoamFile
|
||||||
|
{
|
||||||
|
version 2.0;
|
||||||
|
format ascii;
|
||||||
|
class dictionary;
|
||||||
|
object blockMeshDict;
|
||||||
|
}
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
convertToMeters 1;
|
||||||
|
|
||||||
|
vertices
|
||||||
|
(
|
||||||
|
(-0.04 -0.0075 0)
|
||||||
|
(0.04 -0.075 0)
|
||||||
|
(0.04 0.075 0)
|
||||||
|
(-0.04 0.075 0)
|
||||||
|
(-0.04 -0.075 0.25)
|
||||||
|
(0.04 -0.075 0.25)
|
||||||
|
(0.04 0.075 0.25)
|
||||||
|
(-0.04 0.075 0.25)
|
||||||
|
);
|
||||||
|
|
||||||
|
blocks
|
||||||
|
(
|
||||||
|
hex (0 1 2 3 4 5 6 7) (35 6 110) simpleGrading (1 1 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
edges
|
||||||
|
(
|
||||||
|
);
|
||||||
|
|
||||||
|
boundary
|
||||||
|
(
|
||||||
|
walls
|
||||||
|
{
|
||||||
|
type wall;
|
||||||
|
faces
|
||||||
|
(
|
||||||
|
(0 4 7 3)
|
||||||
|
(2 6 5 1)
|
||||||
|
(1 5 4 0)
|
||||||
|
(3 7 6 2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
inlet
|
||||||
|
{
|
||||||
|
type patch;
|
||||||
|
faces
|
||||||
|
(
|
||||||
|
(0 3 2 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
outlet
|
||||||
|
{
|
||||||
|
type patch;
|
||||||
|
faces
|
||||||
|
(
|
||||||
|
(4 5 6 7)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
mergePatchPairs
|
||||||
|
(
|
||||||
|
);
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user