Commit b30a6faf authored by Mark Olesen's avatar Mark Olesen
Browse files

Merge commit 'OpenCFD/master' into olesenm

parents 7e2a940d 093305d3
......@@ -29,6 +29,36 @@ Description
Basic sub-grid obstacle flame-wrinking enhancement factor model.
Details supplied by J Puttock 2/7/06.
<b> Sub-grid flame area generation <\b>
\f$ n = N - \hat{\dwea{\vec{U}}}.n_{s}.\hat{\dwea{\vec{U}}} \f$
\f$ n_{r} = \sqrt{n} \f$
where:
\f$ \hat{\dwea{\vec{U}}} = \dwea{\vec{U}} / \vert \dwea{\vec{U}}
\vert \f$
\f$ b = \hat{\dwea{\vec{U}}}.B.\hat{\dwea{\vec{U}}} / n_{r} \f$
where:
\f$ B \f$ is the file "B".
\f$ N \f$ is the file "N".
\f$ n_{s} \f$ is the file "ns".
The flame area enhancement factor \f$ \Xi_{sub} \f$ is expected to
approach:
\f[
\Xi_{{sub}_{eq}} =
1 + max(2.2 \sqrt{b}, min(0.34 \frac{\vert \dwea{\vec{U}}
\vert}{{\vec{U}}^{'}}, 1.6)) \times min(\frac{n}{4}, 1)
\f]
SourceFiles
basicSubGrid.C
......
......@@ -25,10 +25,28 @@ License
Class
basicSubGrid
Description
Basic sub-grid obstacle flame-wrinking generation rate coefficient model.
Details supplied by J Puttock 2/7/06.
\f$ G_{sub} \f$ denotes the generation coefficient and it is given by
\f[
G_{sub} = k_{1} /frac{\vert \dwea{\vec{U}} \vert}{L_{obs}}
\frac{/Xi_{{sub}_{eq}}-1}{/Xi_{sub}}
\f]
and the removal:
\f[ - k_{1} /frac{\vert \dwea{\vec{U}} \vert}{L_{sub}}
\frac{\Xi_{sub}-1}{\Xi_{sub}} \f]
Finally, \f$ G_{sub} \f$ is added to generation rate \f$ G_{in} \f$
due to the turbulence.
SourceFiles
basicSubGrid.C
......
......@@ -29,6 +29,50 @@ Description
Basic sub-grid obstacle drag model.
Details supplied by J Puttock 2/7/06.
<b> Sub-grid drag term <\b>
The resistance term (force per unit of volume) is given by:
\f[
R = -\frac{1}{2} \rho \vert \dwea{\vec{U}} \vert \dwea{\vec{U}}.D
\f]
where:
\f$ D \f$ is the tensor field "CR" in \f$ m^{-1} \f$
This is term is treated implicitly in UEqn.H
<b> Sub-grid turbulence generation <\b>
The turbulence source term \f$ G_{R} \f$ occurring in the
\f$ \kappa-\epsilon \f$ equations for the generation of turbulence due
to interaction with unresolved obstacles :
\f$ G_{R} = C_{s}\beta_{\nu}
\mu_{eff} A_{w}^{2}(\dwea{\vec{U}}-\dwea{\vec{U}_{s}})^2 + \frac{1}{2}
\rho \vert \dwea{\vec{U}} \vert \dwea{\vec{U}}.T.\dwea{\vec{U}} \f$
where:
\f$ C_{s} \f$ = 1
\f$ \beta_{\nu} \f$ is the volume porosity (file "betav").
\f$ \mu_{eff} \f$ is the effective viscosity.
\f$ A_{w}^{2}\f$ is the obstacle surface area per unit of volume
(file "Aw").
\f$ \dwea{\vec{U}_{s}} \f$ is the slip velocity and is considered
\f$ \frac{1}{2}. \dwea{\vec{U}} \f$.
\f$ T \f$ is a tensor in the file CT.
The term \f$ G_{R} \f$ is treated explicitly in the \f$ \kappa-\epsilon
\f$ Eqs in the PDRkEpsilon.C file.
SourceFiles
basic.C
......@@ -40,7 +84,6 @@ SourceFiles
#include "PDRDragModel.H"
#include "XiEqModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
......
......@@ -26,7 +26,17 @@ Class
PDRkEpsilon
Description
Standard k-epsilon turbulence model.
Standard k-epsilon turbulence model with additional source terms
corresponding to PDR basic drag model (basic.H)
The turbulence source term \f$ G_{R} \f$ appears in the
\f$ \kappa-\epsilon \f$ equation for the generation of turbulence due to
interaction with unresolved obstacles.
In the \f$ \epsilon \f$ equation \f$ C_{1} G_{R} \f$ is added as a source
term.
In the \f$ \kappa \f$ equation \f$ G_{R} \f$ is added as a source term.
SourceFiles
PDRkEpsilon.C
......
......@@ -27,6 +27,57 @@ Class
Description
Base-class for all Xi models used by the b-Xi combustion model.
See Technical Report SH/RE/01R for details on the PDR modelling.
Xi is given through an algebraic expression (algebraic.H),
by solving a transport equation (transport.H) or a fixed value (fixed.H).
See report TR/HGW/10 for details on the Weller two equations model.
In the algebraic and transport methods \f$\Xi_{eq}\f$ is calculated in
similar way. In the algebraic approach, \f$\Xi_{eq}\f$ is the value used in
the \f$ b \f$ transport equation.
\f$\Xi_{eq}\f$ is calculated as follows:
\f$\Xi_{eq} = 1 + (1 + 2\Xi_{coeff}(0.5 - \dwea{b}))(\Xi^* - 1)\f$
where:
\f$ \dwea{b} \f$ is the regress variable.
\f$ \Xi^* \f$ is the total equilibrium wrinkling combining the effects
of the flame inestability and turbulence interaction and is given by
\f[
\Xi^* = \frac {R}{R - G_\eta - G_{in}}
\f]
where:
\f$ G_\eta \f$ is the generation rate of wrinkling due to turbulence
interaction.
\f$ G_{in} = \kappa \rho_{u}/\rho_{b} \f$ is the generation
rate due to the flame inestability.
By adding the removal rates of the two effects:
\f[
R = G_\eta \frac{\Xi_{\eta_{eq}}}{\Xi_{\eta_{eq}} - 1}
+ G_{in} \frac{\Xi_{{in}_{eq}}}{\Xi_{{in}_{eq}} - 1}
\f]
where:
\f$ R \f$ is the total removal.
\f$ G_\eta \f$ is a model constant.
\f$ \Xi_{\eta_{eq}} \f$ is the flame wrinkling due to turbulence.
\f$ \Xi_{{in}_{eq}} \f$ is the equilibrium level of the flame wrinkling
generated by inestability. It is a constant (default 2.5).
SourceFiles
XiModel.C
......@@ -51,6 +102,8 @@ namespace Foam
Class XiModel Declaration
\*---------------------------------------------------------------------------*/
class XiModel
{
......
......@@ -28,6 +28,33 @@ Class
Description
Laminar flame speed obtained from the SCOPE correlation.
Seven parameters are specified in terms of polynomial functions of
stoichiometry. Two polynomials are fitted, covering different parts of the
flammable range. If the mixture is outside the fitted range, linear
interpolation is used between the extreme of the polynomio and the upper or
lower flammable limit with the Markstein number constant.
Variations of pressure and temperature from the reference values are taken
into account through \f$ pexp \f$ and \f$ texp \f$
The laminar burning velocity fitting polynomial is:
\f$ Su = a_{0}(1+a_{1}x+K+..a_{i}x^{i}..+a_{6}x^{6}) (p/p_{ref})^{pexp}
(T/T_{ref})^{texp} \f$
where:
\f$ a_{i} \f$ are the polinomial coefficients.
\f$ pexp \f$ and \f$ texp \f$ are the pressure and temperature factors
respectively.
\f$ x \f$ is the equivalence ratio.
\f$ T_{ref} \f$ and \f$ p_{ref} \f$ are the temperature and pressure
references for the laminar burning velocity.
SourceFiles
SCOPELaminarFlameSpeed.C
......@@ -125,7 +152,7 @@ class SCOPE
// corrected for temperature and pressure dependence
inline scalar Su0pTphi(scalar p, scalar Tu, scalar phi) const;
//- Laminar flame speed evaluated from the given uniform
//- Laminar flame speed evaluated from the given uniform
// equivalence ratio corrected for temperature and pressure dependence
tmp<volScalarField> Su0pTphi
(
......@@ -134,7 +161,7 @@ class SCOPE
scalar phi
) const;
//- Laminar flame speed evaluated from the given equivalence ratio
//- Laminar flame speed evaluated from the given equivalence ratio
// distribution corrected for temperature and pressure dependence
tmp<volScalarField> Su0pTphi
(
......@@ -144,7 +171,7 @@ class SCOPE
) const;
//- Return the Markstein number
// evaluated from the given equivalence ratio
// evaluated from the given equivalence ratio
tmp<volScalarField> Ma(const volScalarField& phi) const;
//- Construct as copy (not implemented)
......
......@@ -45,6 +45,27 @@ int main(int argc, char *argv[])
Info<< testDict << endl;
{
dictionary someDict;
someDict.add(keyType("a.*", true), "subdictValue");
dictionary dict;
dict.add("someDict", someDict);
dict.add(keyType(".*", true), "parentValue");
Info<< "dict:" << dict << endl;
// Wildcard find.
Info<< "Wildcard find \"abc\" in top directory : "
<< dict.lookup("abc") << endl;
Info<< "Wildcard find \"abc\" in sub directory : "
<< dict.subDict("someDict").lookup("abc")
<< endl;
Info<< "Recursive wildcard find \"def\" in sub directory : "
<< dict.subDict("someDict").lookup("def", true)
<< endl;
}
return 0;
}
......
polyDualMeshApp.C
meshDualiser.C
makePolyDualMesh.C
EXE = $(FOAM_APPBIN)/polyDualMesh
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/conversion/lnInclude
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude
EXE_LIBS = \
-lmeshTools -lconversion
-lfiniteVolume \
-ldynamicMesh \
-lmeshTools
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2007 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
Description
Calculate the dual of a polyMesh. Adheres to all the feature&patch edges.
Feature angle:
convex features : point becomes single boundary cell with multiple
boundary faces.
concave features: point becomes multiple boundary cells.
-splitAllFaces:
Normally only constructs a single face between two cells. This single face
might be too distorted. splitAllFaces will create a single face for every
original cell the face passes through. The mesh will thus have
multiple faces inbetween two cells! (so is not strictly upper-triangular
anymore - checkMesh will complain)
-doNotPreserveFaceZones:
By default all faceZones are preserved by marking all faces, edges and
points on them as features. The -doNotPreserveFaceZones disables this
behaviour.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "fvMesh.H"
#include "mathematicalConstants.H"
#include "polyTopoChange.H"
#include "mapPolyMesh.H"
#include "PackedList.H"
#include "meshTools.H"
#include "OFstream.H"
#include "meshDualiser.H"
#include "ReadFields.H"
#include "volFields.H"
#include "surfaceFields.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Naive feature detection. All boundary edges with angle > featureAngle become
// feature edges. All points on feature edges become feature points. All
// boundary faces become feature faces.
void simpleMarkFeatures
(
const polyMesh& mesh,
const PackedList<1>& isBoundaryEdge,
const scalar featureAngle,
const bool doNotPreserveFaceZones,
labelList& featureFaces,
labelList& featureEdges,
labelList& singleCellFeaturePoints,
labelList& multiCellFeaturePoints
)
{
scalar minCos = Foam::cos(featureAngle * mathematicalConstant::pi/180.0);
const polyBoundaryMesh& patches = mesh.boundaryMesh();
// Working sets
labelHashSet featureEdgeSet;
labelHashSet singleCellFeaturePointSet;
labelHashSet multiCellFeaturePointSet;
// 1. Mark all edges between patches
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
forAll(patches, patchI)
{
const polyPatch& pp = patches[patchI];
const labelList& meshEdges = pp.meshEdges();
// All patch corner edges. These need to be feature points & edges!
for (label edgeI = pp.nInternalEdges(); edgeI < pp.nEdges(); edgeI++)
{
label meshEdgeI = meshEdges[edgeI];
featureEdgeSet.insert(meshEdgeI);
singleCellFeaturePointSet.insert(mesh.edges()[meshEdgeI][0]);
singleCellFeaturePointSet.insert(mesh.edges()[meshEdgeI][1]);
}
}
// 2. Mark all geometric feature edges
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Make distinction between convex features where the boundary point becomes
// a single cell and concave features where the boundary point becomes
// multiple 'half' cells.
// Addressing for all outside faces
primitivePatch allBoundary
(
SubList<face>
(
mesh.faces(),
mesh.nFaces()-mesh.nInternalFaces(),
mesh.nInternalFaces()
),
mesh.points()
);
// Check for non-manifold points (surface pinched at point)
allBoundary.checkPointManifold(false, &singleCellFeaturePointSet);
// Check for non-manifold edges (surface pinched at edge)
const labelListList& edgeFaces = allBoundary.edgeFaces();
const labelList& meshPoints = allBoundary.meshPoints();
forAll(edgeFaces, edgeI)
{
const labelList& eFaces = edgeFaces[edgeI];
if (eFaces.size() > 2)
{
const edge& e = allBoundary.edges()[edgeI];
//Info<< "Detected non-manifold boundary edge:" << edgeI
// << " coords:"
// << allBoundary.points()[meshPoints[e[0]]]
// << allBoundary.points()[meshPoints[e[1]]] << endl;
singleCellFeaturePointSet.insert(meshPoints[e[0]]);
singleCellFeaturePointSet.insert(meshPoints[e[1]]);
}
}
// Check for features.
forAll(edgeFaces, edgeI)
{
const labelList& eFaces = edgeFaces[edgeI];
if (eFaces.size() == 2)
{
label f0 = eFaces[0];
label f1 = eFaces[1];
// check angle
const vector& n0 = allBoundary.faceNormals()[f0];
const vector& n1 = allBoundary.faceNormals()[f1];
if ((n0 & n1) < minCos)
{
const edge& e = allBoundary.edges()[edgeI];
label v0 = meshPoints[e[0]];
label v1 = meshPoints[e[1]];
label meshEdgeI = meshTools::findEdge(mesh, v0, v1);
featureEdgeSet.insert(meshEdgeI);
// Check if convex or concave by looking at angle
// between face centres and normal
vector c1c0
(
allBoundary[f1].centre(allBoundary.points())
- allBoundary[f0].centre(allBoundary.points())
);
if ((c1c0 & n0) > SMALL)
{
// Found concave edge. Make into multiCell features
Info<< "Detected concave feature edge:" << edgeI
<< " cos:" << (c1c0 & n0)
<< " coords:"
<< allBoundary.points()[v0]
<< allBoundary.points()[v1]
<< endl;
singleCellFeaturePointSet.erase(v0);
multiCellFeaturePointSet.insert(v0);
singleCellFeaturePointSet.erase(v1);
multiCellFeaturePointSet.insert(v1);
}
else
{
// Convex. singleCell feature.
if (!multiCellFeaturePointSet.found(v0))
{
singleCellFeaturePointSet.insert(v0);
}
if (!multiCellFeaturePointSet.found(v1))
{
singleCellFeaturePointSet.insert(v1);
}
}
}
}
}
// 3. Mark all feature faces
// ~~~~~~~~~~~~~~~~~~~~~~~~~
// Face centres that need inclusion in the dual mesh
labelHashSet featureFaceSet(mesh.nFaces()-mesh.nInternalFaces());
// A. boundary faces.
for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++)
{
featureFaceSet.insert(faceI);
}
// B. face zones.
const faceZoneMesh& faceZones = mesh.faceZones();
if (doNotPreserveFaceZones)
{
if (faceZones.size() > 0)
{
WarningIn("simpleMarkFeatures(..)")
<< "Detected " << faceZones.size()
<< " faceZones. These will not be preserved."
<< endl;
}
}
else
{
if (faceZones.size() > 0)
{
Info<< "Detected " << faceZones.size()
<< " faceZones. Preserving these by marking their"
<< " points, edges and faces as features." << endl;
}
forAll(faceZones, zoneI)
{
const faceZone& fz = faceZones[zoneI];
Info<< "Inserting all faces in faceZone " << fz.name()
<< " as features." << endl;
forAll(fz, i)
{
label faceI = fz[i];
const face& f = mesh.faces()[faceI];
const labelList& fEdges = mesh.faceEdges()[faceI];
featureFaceSet.insert(faceI);
forAll(f, fp)
{
// Mark point as multi cell point (since both sides of
// face should have different cells)
singleCellFeaturePointSet.erase(f[fp]);
multiCellFeaturePointSet.insert(f[fp]);
// Make sure there are points on the edges.
featureEdgeSet.insert(fEdges[fp]);
}
}
}
}
// Transfer to arguments