mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: tet decomposed particle tracking.
Squashed merge of particleInteractions up to commit e7cb5bcf0315c359539ef1e715e1d51991343391
This commit is contained in:
@ -2,6 +2,7 @@ EXE_INC = \
|
|||||||
-I../engineFoam \
|
-I../engineFoam \
|
||||||
-I$(LIB_SRC)/turbulenceModels/compressible/turbulenceModel \
|
-I$(LIB_SRC)/turbulenceModels/compressible/turbulenceModel \
|
||||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
-I$(LIB_SRC)/lagrangian/dieselSpray/lnInclude \
|
-I$(LIB_SRC)/lagrangian/dieselSpray/lnInclude \
|
||||||
-I$(LIB_SRC)/thermophysicalModels/liquids/lnInclude \
|
-I$(LIB_SRC)/thermophysicalModels/liquids/lnInclude \
|
||||||
-I$(LIB_SRC)/thermophysicalModels/liquidMixture/lnInclude \
|
-I$(LIB_SRC)/thermophysicalModels/liquidMixture/lnInclude \
|
||||||
@ -24,6 +25,7 @@ EXE_LIBS = \
|
|||||||
-lreactionThermophysicalModels \
|
-lreactionThermophysicalModels \
|
||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
-llagrangian \
|
-llagrangian \
|
||||||
|
-lmeshTools \
|
||||||
-ldieselSpray \
|
-ldieselSpray \
|
||||||
-lliquids \
|
-lliquids \
|
||||||
-lliquidMixture \
|
-lliquidMixture \
|
||||||
|
|||||||
@ -3,6 +3,7 @@ EXE_INC = \
|
|||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
-I$(LIB_SRC)/turbulenceModels/compressible/turbulenceModel \
|
-I$(LIB_SRC)/turbulenceModels/compressible/turbulenceModel \
|
||||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
-I$(LIB_SRC)/lagrangian/dieselSpray/lnInclude \
|
-I$(LIB_SRC)/lagrangian/dieselSpray/lnInclude \
|
||||||
-I$(LIB_SRC)/thermophysicalModels/liquids/lnInclude \
|
-I$(LIB_SRC)/thermophysicalModels/liquids/lnInclude \
|
||||||
-I$(LIB_SRC)/thermophysicalModels/liquidMixture/lnInclude \
|
-I$(LIB_SRC)/thermophysicalModels/liquidMixture/lnInclude \
|
||||||
@ -21,6 +22,7 @@ EXE_LIBS = \
|
|||||||
-lcompressibleLESModels \
|
-lcompressibleLESModels \
|
||||||
-lreactionThermophysicalModels \
|
-lreactionThermophysicalModels \
|
||||||
-llagrangian \
|
-llagrangian \
|
||||||
|
-lmeshTools \
|
||||||
-ldieselSpray \
|
-ldieselSpray \
|
||||||
-lliquids \
|
-lliquids \
|
||||||
-lliquidMixture \
|
-lliquidMixture \
|
||||||
|
|||||||
@ -9,4 +9,3 @@ EXE_LIBS = \
|
|||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
-llagrangian \
|
-llagrangian \
|
||||||
-ldsmc
|
-ldsmc
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
incompressibleUncoupledKinematicParcelDyMFoam.C
|
||||||
|
|
||||||
|
EXE = $(FOAM_APPBIN)/incompressibleUncoupledKinematicParcelDyMFoam
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
||||||
|
-I$(LIB_SRC)/lagrangian/intermediate/lnInclude \
|
||||||
|
-I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \
|
||||||
|
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
|
||||||
|
-I$(LIB_SRC)/thermophysicalModels/reactionThermo/lnInclude \
|
||||||
|
-I$(LIB_SRC)/thermophysicalModels/radiation/lnInclude \
|
||||||
|
-I$(LIB_SRC)/turbulenceModels/incompressible/turbulenceModel \
|
||||||
|
-I$(LIB_SRC)/transportModels \
|
||||||
|
-I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
|
-I$(LIB_SRC)/surfaceFilmModels/lnInclude \
|
||||||
|
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
||||||
|
-I$(LIB_SRC)/dynamicFvMesh/lnInclude
|
||||||
|
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-llagrangian \
|
||||||
|
-llagrangianIntermediate \
|
||||||
|
-lthermophysicalFunctions \
|
||||||
|
-lbasicThermophysicalModels \
|
||||||
|
-lspecie \
|
||||||
|
-lradiation \
|
||||||
|
-lincompressibleRASModels \
|
||||||
|
-lincompressibleLESModels \
|
||||||
|
-lincompressibleTransportModels \
|
||||||
|
-lfiniteVolume \
|
||||||
|
-lmeshTools \
|
||||||
|
-lsurfaceFilmModels \
|
||||||
|
-ldynamicMesh \
|
||||||
|
-ldynamicFvMesh \
|
||||||
|
-ltopoChangerFvMesh
|
||||||
@ -0,0 +1,147 @@
|
|||||||
|
Info<< "\nReading transportProperties\n" << endl;
|
||||||
|
|
||||||
|
IOdictionary transportProperties
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"transportProperties",
|
||||||
|
runTime.constant(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ_IF_MODIFIED,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
dimensionedScalar rhoInfValue
|
||||||
|
(
|
||||||
|
transportProperties.lookup("rhoInf")
|
||||||
|
);
|
||||||
|
|
||||||
|
volScalarField rhoInf
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"rho",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh,
|
||||||
|
rhoInfValue
|
||||||
|
);
|
||||||
|
|
||||||
|
Info<< "Reading field U\n" << endl;
|
||||||
|
volVectorField U
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"U",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
#include "createPhi.H"
|
||||||
|
|
||||||
|
Info<< "Creating turbulence model\n" << endl;
|
||||||
|
|
||||||
|
singlePhaseTransportModel laminarTransport(U, phi);
|
||||||
|
|
||||||
|
const volScalarField nu = laminarTransport.nu();
|
||||||
|
|
||||||
|
autoPtr<incompressible::turbulenceModel> turbulence
|
||||||
|
(
|
||||||
|
incompressible::turbulenceModel::New(U, phi, laminarTransport)
|
||||||
|
);
|
||||||
|
|
||||||
|
volScalarField mu
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"mu",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
nu*rhoInfValue
|
||||||
|
);
|
||||||
|
|
||||||
|
word kinematicCloudName("kinematicCloud");
|
||||||
|
args.optionReadIfPresent("cloudName", kinematicCloudName);
|
||||||
|
|
||||||
|
Info<< "Constructing kinematicCloud " << kinematicCloudName << endl;
|
||||||
|
basicKinematicCloud kinematicCloud
|
||||||
|
(
|
||||||
|
kinematicCloudName,
|
||||||
|
rhoInf,
|
||||||
|
U,
|
||||||
|
mu,
|
||||||
|
g
|
||||||
|
);
|
||||||
|
|
||||||
|
IOobject Hheader
|
||||||
|
(
|
||||||
|
"H",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ
|
||||||
|
);
|
||||||
|
|
||||||
|
autoPtr<volVectorField> HPtr_;
|
||||||
|
|
||||||
|
if (Hheader.headerOk())
|
||||||
|
{
|
||||||
|
Info<< "\nReading field H\n" << endl;
|
||||||
|
|
||||||
|
HPtr_.reset
|
||||||
|
(
|
||||||
|
new volVectorField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"H",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IOobject HdotGradHheader
|
||||||
|
(
|
||||||
|
"HdotGradH",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::NO_READ
|
||||||
|
);
|
||||||
|
|
||||||
|
autoPtr<volVectorField> HdotGradHPtr_;
|
||||||
|
|
||||||
|
if (HdotGradHheader.headerOk())
|
||||||
|
{
|
||||||
|
Info<< "Reading field HdotGradH" << endl;
|
||||||
|
|
||||||
|
HdotGradHPtr_.reset
|
||||||
|
(
|
||||||
|
new volVectorField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"HdotGradH",
|
||||||
|
runTime.timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2008-2010 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 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
|
||||||
|
uncoupledKinematicParcelFoam
|
||||||
|
|
||||||
|
Description
|
||||||
|
Transient solver for the passive transport of a single kinematic
|
||||||
|
particle could.
|
||||||
|
|
||||||
|
Uses a pre-calculated velocity field to evolve the cloud.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "fvCFD.H"
|
||||||
|
#include "dynamicFvMesh.H"
|
||||||
|
#include "singlePhaseTransportModel.H"
|
||||||
|
#include "turbulenceModel.H"
|
||||||
|
#include "basicKinematicCloud.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
argList::addOption
|
||||||
|
(
|
||||||
|
"cloudName",
|
||||||
|
"name",
|
||||||
|
"specify alternative cloud name. default is 'kinematicCloud'"
|
||||||
|
);
|
||||||
|
|
||||||
|
#include "setRootCase.H"
|
||||||
|
#include "createTime.H"
|
||||||
|
# include "createDynamicFvMesh.H"
|
||||||
|
|
||||||
|
#include "readGravitationalAcceleration.H"
|
||||||
|
#include "createFields.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Info<< "\nStarting time loop\n" << endl;
|
||||||
|
|
||||||
|
while (runTime.loop())
|
||||||
|
{
|
||||||
|
Info<< "Time = " << runTime.timeName() << nl << endl;
|
||||||
|
|
||||||
|
mesh.update();
|
||||||
|
|
||||||
|
U.correctBoundaryConditions();
|
||||||
|
|
||||||
|
Info<< "Evolving " << kinematicCloud.name() << endl;
|
||||||
|
|
||||||
|
laminarTransport.correct();
|
||||||
|
|
||||||
|
mu = nu*rhoInfValue;
|
||||||
|
|
||||||
|
kinematicCloud.evolve();
|
||||||
|
|
||||||
|
runTime.write();
|
||||||
|
|
||||||
|
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
|
||||||
|
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
|
||||||
|
<< nl << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< "End\n" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -29,6 +29,8 @@ License
|
|||||||
#include "IStringStream.H"
|
#include "IStringStream.H"
|
||||||
#include "octree.H"
|
#include "octree.H"
|
||||||
#include "octreeDataCell.H"
|
#include "octreeDataCell.H"
|
||||||
|
#include "indexedOctree.H"
|
||||||
|
#include "treeDataCell.H"
|
||||||
#include "OFstream.H"
|
#include "OFstream.H"
|
||||||
|
|
||||||
using namespace Foam;
|
using namespace Foam;
|
||||||
@ -44,11 +46,13 @@ int main(int argc, char *argv[])
|
|||||||
# include "createTime.H"
|
# include "createTime.H"
|
||||||
# include "createMesh.H"
|
# include "createMesh.H"
|
||||||
|
|
||||||
|
label nReps = 100000;
|
||||||
|
|
||||||
const point sample = args.argRead<point>(1);
|
const point sample = args.argRead<point>(1);
|
||||||
|
|
||||||
treeBoundBox meshBb(mesh.points());
|
treeBoundBox meshBb(mesh.bounds());
|
||||||
|
|
||||||
// Calculate typical cell releated size to shift bb by.
|
// Calculate typical cell related size to shift bb by.
|
||||||
scalar typDim = meshBb.avgDim()/(2.0*Foam::cbrt(scalar(mesh.nCells())));
|
scalar typDim = meshBb.avgDim()/(2.0*Foam::cbrt(scalar(mesh.nCells())));
|
||||||
|
|
||||||
treeBoundBox shiftedBb
|
treeBoundBox shiftedBb
|
||||||
@ -57,16 +61,13 @@ int main(int argc, char *argv[])
|
|||||||
meshBb.max() + vector(typDim, typDim, typDim)
|
meshBb.max() + vector(typDim, typDim, typDim)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
Info<< "Mesh" << endl;
|
Info<< "Mesh" << endl;
|
||||||
Info<< " bounding box : " << meshBb << endl;
|
Info<< " bounding box : " << meshBb << endl;
|
||||||
Info<< " bounding box (shifted) : " << shiftedBb << endl;
|
Info<< " bounding box (shifted) : " << shiftedBb << endl;
|
||||||
Info<< " typical dimension : " << shiftedBb.typDim() << endl;
|
Info<< " typical dimension : " << shiftedBb.typDim() << endl;
|
||||||
|
|
||||||
|
Info<< "Initialised mesh in "
|
||||||
/*
|
<< runTime.cpuTimeIncrement() << " s" << endl;
|
||||||
* Now we have allBb and shiftedBb
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Wrap indices and mesh information into helper object
|
// Wrap indices and mesh information into helper object
|
||||||
octreeDataCell shapes(mesh);
|
octreeDataCell shapes(mesh);
|
||||||
@ -80,14 +81,52 @@ int main(int argc, char *argv[])
|
|||||||
10.0 // maximum ratio of cubes v.s. cells
|
10.0 // maximum ratio of cubes v.s. cells
|
||||||
);
|
);
|
||||||
|
|
||||||
Info<< "Point:" << sample << " is in shape "
|
for (label i = 0; i < nReps - 1 ; i++)
|
||||||
<< oc.find(sample) << nl
|
{
|
||||||
<< "Point:" << sample << " is in cell "
|
oc.find(sample);
|
||||||
<< mesh.findCell(sample) << endl;
|
}
|
||||||
|
|
||||||
|
Info<< "Point:" << sample << " is in shape "
|
||||||
|
<< oc.find(sample) << endl;
|
||||||
|
|
||||||
oc.printStats(Info);
|
oc.printStats(Info);
|
||||||
|
|
||||||
|
Info<< "Found in octree " << nReps << " times in "
|
||||||
|
<< runTime.cpuTimeIncrement() << " s" << endl;
|
||||||
|
|
||||||
|
indexedOctree<treeDataCell> ioc
|
||||||
|
(
|
||||||
|
treeDataCell(true, mesh),
|
||||||
|
shiftedBb,
|
||||||
|
8, // maxLevel
|
||||||
|
10, // leafsize
|
||||||
|
3.0 // duplicity
|
||||||
|
);
|
||||||
|
|
||||||
|
for (label i = 0; i < nReps - 1 ; i++)
|
||||||
|
{
|
||||||
|
ioc.findInside(sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< "Point:" << sample << " is in shape "
|
||||||
|
<< ioc.findInside(sample)
|
||||||
|
<< ", where the possible cells were:" << nl
|
||||||
|
<< ioc.findIndices(sample)
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
Info<< "Found in indexedOctree " << nReps << " times in "
|
||||||
|
<< runTime.cpuTimeIncrement() << " s" << endl;
|
||||||
|
|
||||||
|
for (label i = 0; i < nReps - 1 ; i++)
|
||||||
|
{
|
||||||
|
mesh.findCell(sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< "Point:" << sample << " is in cell "
|
||||||
|
<< mesh.findCell(sample) << endl;
|
||||||
|
|
||||||
|
Info<< "Found in mesh.findCell " << nReps << " times in "
|
||||||
|
<< runTime.cpuTimeIncrement() << " s" << endl;
|
||||||
|
|
||||||
Info<< "End\n" << endl;
|
Info<< "End\n" << endl;
|
||||||
|
|
||||||
|
|||||||
@ -341,11 +341,14 @@ meshQualityControls
|
|||||||
// Set to very negative number (e.g. -1E30) to disable.
|
// Set to very negative number (e.g. -1E30) to disable.
|
||||||
minVol 1e-13;
|
minVol 1e-13;
|
||||||
|
|
||||||
//- Minimum tet volume. Is absolute volume of the tet formed by the
|
//- Minimum quality of the tet formed by the face-centre
|
||||||
// face-centre decomposition triangle and the cell centre.
|
// and variable base point minimum decomposition triangles and
|
||||||
// Set to a sensible fraction of the smallest cell volume expected.
|
// the cell centre. Set to very negative number (e.g. -1E30) to
|
||||||
// Set to very negative number (e.g. -1E30) to disable.
|
// disable.
|
||||||
minTetVol 1e-20;
|
// <0 = inside out tet,
|
||||||
|
// 0 = flat tet
|
||||||
|
// 1 = regular tet
|
||||||
|
minTetQuality 1e-9;
|
||||||
|
|
||||||
//- Minimum face area. Set to <0 to disable.
|
//- Minimum face area. Set to <0 to disable.
|
||||||
minArea -1;
|
minArea -1;
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include "EdgeMap.H"
|
#include "EdgeMap.H"
|
||||||
#include "wedgePolyPatch.H"
|
#include "wedgePolyPatch.H"
|
||||||
#include "unitConversion.H"
|
#include "unitConversion.H"
|
||||||
|
#include "polyMeshTetDecomposition.H"
|
||||||
|
|
||||||
|
|
||||||
// Find wedge with opposite orientation. Note: does not actually check that
|
// Find wedge with opposite orientation. Note: does not actually check that
|
||||||
@ -413,7 +414,6 @@ Foam::label Foam::checkGeometry(const polyMesh& mesh, const bool allGeometry)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
faceSet faces(mesh, "wrongOrientedFaces", mesh.nFaces()/100 + 1);
|
faceSet faces(mesh, "wrongOrientedFaces", mesh.nFaces()/100 + 1);
|
||||||
if (mesh.checkFacePyramids(true, -SMALL, &faces))
|
if (mesh.checkFacePyramids(true, -SMALL, &faces))
|
||||||
@ -433,25 +433,6 @@ Foam::label Foam::checkGeometry(const polyMesh& mesh, const bool allGeometry)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
faceSet faces(mesh, "wrongOrientedTriangleFaces", mesh.nFaces()/100+1);
|
|
||||||
if (mesh.checkFaceTets(true, 0, &faces))
|
|
||||||
{
|
|
||||||
noFailedChecks++;
|
|
||||||
|
|
||||||
label nFaces = returnReduce(faces.size(), sumOp<label>());
|
|
||||||
|
|
||||||
if (nFaces > 0)
|
|
||||||
{
|
|
||||||
Info<< " <<Writing " << nFaces
|
|
||||||
<< " faces with incorrectly orientated triangles to set "
|
|
||||||
<< faces.name() << endl;
|
|
||||||
faces.instance() = mesh.pointsInstance();
|
|
||||||
faces.write();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
faceSet faces(mesh, "skewFaces", mesh.nFaces()/100+1);
|
faceSet faces(mesh, "skewFaces", mesh.nFaces()/100+1);
|
||||||
if (mesh.checkFaceSkewness(true, &faces))
|
if (mesh.checkFaceSkewness(true, &faces))
|
||||||
@ -470,6 +451,35 @@ Foam::label Foam::checkGeometry(const polyMesh& mesh, const bool allGeometry)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allGeometry)
|
||||||
|
{
|
||||||
|
faceSet faces(mesh, "lowQualityTetFaces", mesh.nFaces()/100+1);
|
||||||
|
if
|
||||||
|
(
|
||||||
|
polyMeshTetDecomposition::checkFaceTets
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
polyMeshTetDecomposition::minTetQuality,
|
||||||
|
true,
|
||||||
|
&faces
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
noFailedChecks++;
|
||||||
|
|
||||||
|
label nFaces = returnReduce(faces.size(), sumOp<label>());
|
||||||
|
|
||||||
|
if (nFaces > 0)
|
||||||
|
{
|
||||||
|
Info<< " <<Writing " << nFaces
|
||||||
|
<< " faces with low quality or negative volume "
|
||||||
|
<< "decomposition tets to set " << faces.name() << endl;
|
||||||
|
faces.instance() = mesh.pointsInstance();
|
||||||
|
faces.write();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (allGeometry)
|
if (allGeometry)
|
||||||
{
|
{
|
||||||
// Note use of nPoints since don't want edge construction.
|
// Note use of nPoints since don't want edge construction.
|
||||||
|
|||||||
@ -558,7 +558,6 @@ int main(int argc, char *argv[])
|
|||||||
lagrangianScalarFieldFields
|
lagrangianScalarFieldFields
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
lagrangianFieldDecomposer::readFields
|
lagrangianFieldDecomposer::readFields
|
||||||
(
|
(
|
||||||
cloudI,
|
cloudI,
|
||||||
@ -687,6 +686,19 @@ int main(int argc, char *argv[])
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
labelIOList faceProcAddressing
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"faceProcAddressing",
|
||||||
|
procMesh.facesInstance(),
|
||||||
|
procMesh.meshSubDir,
|
||||||
|
procMesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
labelIOList cellProcAddressing
|
labelIOList cellProcAddressing
|
||||||
(
|
(
|
||||||
IOobject
|
IOobject
|
||||||
@ -728,19 +740,6 @@ int main(int argc, char *argv[])
|
|||||||
|| surfaceTensorFields.size()
|
|| surfaceTensorFields.size()
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
labelIOList faceProcAddressing
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"faceProcAddressing",
|
|
||||||
procMesh.facesInstance(),
|
|
||||||
procMesh.meshSubDir,
|
|
||||||
procMesh,
|
|
||||||
IOobject::MUST_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
fvFieldDecomposer fieldDecomposer
|
fvFieldDecomposer fieldDecomposer
|
||||||
(
|
(
|
||||||
mesh,
|
mesh,
|
||||||
@ -814,6 +813,7 @@ int main(int argc, char *argv[])
|
|||||||
(
|
(
|
||||||
mesh,
|
mesh,
|
||||||
procMesh,
|
procMesh,
|
||||||
|
faceProcAddressing,
|
||||||
cellProcAddressing,
|
cellProcAddressing,
|
||||||
cloudDirs[cloudI],
|
cloudDirs[cloudI],
|
||||||
lagrangianPositions[cloudI],
|
lagrangianPositions[cloudI],
|
||||||
|
|||||||
@ -35,6 +35,7 @@ Foam::lagrangianFieldDecomposer::lagrangianFieldDecomposer
|
|||||||
(
|
(
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const polyMesh& procMesh,
|
const polyMesh& procMesh,
|
||||||
|
const labelList& faceProcAddressing,
|
||||||
const labelList& cellProcAddressing,
|
const labelList& cellProcAddressing,
|
||||||
const word& cloudName,
|
const word& cloudName,
|
||||||
const Cloud<indexedParticle>& lagrangianPositions,
|
const Cloud<indexedParticle>& lagrangianPositions,
|
||||||
@ -47,6 +48,14 @@ Foam::lagrangianFieldDecomposer::lagrangianFieldDecomposer
|
|||||||
{
|
{
|
||||||
label pi = 0;
|
label pi = 0;
|
||||||
|
|
||||||
|
// faceProcAddressing not required currently
|
||||||
|
// labelList decodedProcFaceAddressing(faceProcAddressing.size());
|
||||||
|
|
||||||
|
// forAll(faceProcAddressing, i)
|
||||||
|
// {
|
||||||
|
// decodedProcFaceAddressing[i] = mag(faceProcAddressing[i]) - 1;
|
||||||
|
// }
|
||||||
|
|
||||||
forAll(cellProcAddressing, procCelli)
|
forAll(cellProcAddressing, procCelli)
|
||||||
{
|
{
|
||||||
label celli = cellProcAddressing[procCelli];
|
label celli = cellProcAddressing[procCelli];
|
||||||
@ -60,6 +69,33 @@ Foam::lagrangianFieldDecomposer::lagrangianFieldDecomposer
|
|||||||
const indexedParticle& ppi = *iter();
|
const indexedParticle& ppi = *iter();
|
||||||
particleIndices_[pi++] = ppi.index();
|
particleIndices_[pi++] = ppi.index();
|
||||||
|
|
||||||
|
// label mappedTetFace = findIndex
|
||||||
|
// (
|
||||||
|
// decodedProcFaceAddressing,
|
||||||
|
// ppi.tetFace()
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (mappedTetFace == -1)
|
||||||
|
// {
|
||||||
|
// FatalErrorIn
|
||||||
|
// (
|
||||||
|
// "Foam::lagrangianFieldDecomposer"
|
||||||
|
// "::lagrangianFieldDecomposer"
|
||||||
|
// "("
|
||||||
|
// "const polyMesh& mesh, "
|
||||||
|
// "const polyMesh& procMesh, "
|
||||||
|
// "const labelList& faceProcAddressing, "
|
||||||
|
// "const labelList& cellProcAddressing, "
|
||||||
|
// "const word& cloudName, "
|
||||||
|
// "const Cloud<indexedParticle>& "
|
||||||
|
// "lagrangianPositions, "
|
||||||
|
// "const List<SLList<indexedParticle*>*>& "
|
||||||
|
// "cellParticles"
|
||||||
|
// ")"
|
||||||
|
// ) << "Face lookup failure." << nl
|
||||||
|
// << abort(FatalError);
|
||||||
|
// }
|
||||||
|
|
||||||
positions_.append
|
positions_.append
|
||||||
(
|
(
|
||||||
new passiveParticle
|
new passiveParticle
|
||||||
|
|||||||
@ -84,6 +84,7 @@ public:
|
|||||||
(
|
(
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const polyMesh& procMesh,
|
const polyMesh& procMesh,
|
||||||
|
const labelList& faceProcAddressing,
|
||||||
const labelList& cellProcAddressing,
|
const labelList& cellProcAddressing,
|
||||||
const word& cloudName,
|
const word& cloudName,
|
||||||
const Cloud<indexedParticle>& lagrangianPositions,
|
const Cloud<indexedParticle>& lagrangianPositions,
|
||||||
|
|||||||
@ -51,7 +51,7 @@ void Foam::lagrangianFieldDecomposer::readFields
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
label lagrangianFieldi=0;
|
label lagrangianFieldi = 0;
|
||||||
forAllIter(IOobjectList, lagrangianTypeObjects, iter)
|
forAllIter(IOobjectList, lagrangianTypeObjects, iter)
|
||||||
{
|
{
|
||||||
lagrangianFields[cloudI].set
|
lagrangianFields[cloudI].set
|
||||||
@ -91,7 +91,7 @@ void Foam::lagrangianFieldDecomposer::readFieldFields
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
label lagrangianFieldi=0;
|
label lagrangianFieldi = 0;
|
||||||
|
|
||||||
forAllIter(IOobjectList, lagrangianTypeObjectsA, iter)
|
forAllIter(IOobjectList, lagrangianTypeObjectsA, iter)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
/* -DFULLDEBUG -g -O0 */ \
|
/* -DFULLDEBUG -g -O0 */ \
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude
|
-I$(LIB_SRC)/lagrangian/basic/lnInclude
|
||||||
|
|
||||||
EXE_LIBS = \
|
EXE_LIBS = \
|
||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
|
-lmeshTools \
|
||||||
-lgenericPatchFields \
|
-lgenericPatchFields \
|
||||||
-llagrangian
|
-llagrangian
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
||||||
-I$(LIB_SRC)/conversion/lnInclude
|
-I$(LIB_SRC)/conversion/lnInclude
|
||||||
|
|
||||||
EXE_LIBS = \
|
EXE_LIBS = \
|
||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
-llagrangian \
|
-llagrangian \
|
||||||
|
-lmeshTools \
|
||||||
-lgenericPatchFields \
|
-lgenericPatchFields \
|
||||||
-lconversion
|
-lconversion
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude
|
-I$(LIB_SRC)/lagrangian/basic/lnInclude
|
||||||
|
|
||||||
EXE_LIBS = \
|
EXE_LIBS = \
|
||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
|
-lmeshTools \
|
||||||
-lgenericPatchFields \
|
-lgenericPatchFields \
|
||||||
-llagrangian
|
-llagrangian
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
-I$(LIB_SRC)/sampling/lnInclude \
|
-I$(LIB_SRC)/sampling/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
-I$(LIB_SRC)/turbulenceModels/incompressible/lnInclude \
|
-I$(LIB_SRC)/turbulenceModels/incompressible/lnInclude \
|
||||||
-I$(LIB_SRC)/transportModels/incompressible/lnInclude \
|
-I$(LIB_SRC)/transportModels/incompressible/lnInclude \
|
||||||
-I$(LIB_SRC)/lagrangian/lnInclude \
|
-I$(LIB_SRC)/lagrangian/lnInclude \
|
||||||
@ -14,5 +15,6 @@ EXE_INC = \
|
|||||||
|
|
||||||
EXE_LIBS = \
|
EXE_LIBS = \
|
||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
|
-lmeshTools \
|
||||||
-lgenericPatchFields \
|
-lgenericPatchFields \
|
||||||
-llagrangian
|
-llagrangian
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
-I$(LIB_SRC)/browser/lnInclude \
|
-I$(LIB_SRC)/browser/lnInclude \
|
||||||
-I$(LIB_SRC)/sampling/lnInclude \
|
-I$(LIB_SRC)/sampling/lnInclude \
|
||||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude
|
-I$(LIB_SRC)/lagrangian/basic/lnInclude
|
||||||
@ -7,6 +8,7 @@ EXE_INC = \
|
|||||||
LIB_LIBS = \
|
LIB_LIBS = \
|
||||||
-lOpenFOAM \
|
-lOpenFOAM \
|
||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
|
-lmeshTools \
|
||||||
-lgenericPatchFields \
|
-lgenericPatchFields \
|
||||||
-llagrangian \
|
-llagrangian \
|
||||||
$(PROJECT_LIBS)
|
$(PROJECT_LIBS)
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude
|
-I$(LIB_SRC)/lagrangian/basic/lnInclude
|
||||||
|
|
||||||
EXE_LIBS = \
|
EXE_LIBS = \
|
||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
|
-lmeshTools \
|
||||||
-lgenericPatchFields \
|
-lgenericPatchFields \
|
||||||
-llagrangian
|
-llagrangian
|
||||||
|
|||||||
@ -9,4 +9,3 @@ EXE_LIBS = \
|
|||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
-llagrangian \
|
-llagrangian \
|
||||||
-ldsmc
|
-ldsmc
|
||||||
|
|
||||||
|
|||||||
@ -37,6 +37,7 @@ Description
|
|||||||
#include "GeometricField.H"
|
#include "GeometricField.H"
|
||||||
#include "meshToMesh.H"
|
#include "meshToMesh.H"
|
||||||
#include "IOobjectList.H"
|
#include "IOobjectList.H"
|
||||||
|
#include "IOFieldField.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -56,11 +57,13 @@ void MapLagrangianFields
|
|||||||
{
|
{
|
||||||
const fvMesh& meshTarget = meshToMeshInterp.toMesh();
|
const fvMesh& meshTarget = meshToMeshInterp.toMesh();
|
||||||
|
|
||||||
|
{
|
||||||
IOobjectList fields = objects.lookupClass(IOField<Type>::typeName);
|
IOobjectList fields = objects.lookupClass(IOField<Type>::typeName);
|
||||||
|
|
||||||
forAllIter(IOobjectList, fields, fieldIter)
|
forAllIter(IOobjectList, fields, fieldIter)
|
||||||
{
|
{
|
||||||
Info<< " mapping lagrangian field " << fieldIter()->name() << endl;
|
Info<< " mapping lagrangian field "
|
||||||
|
<< fieldIter()->name() << endl;
|
||||||
|
|
||||||
// Read field (does not need mesh)
|
// Read field (does not need mesh)
|
||||||
IOField<Type> fieldSource(*fieldIter());
|
IOField<Type> fieldSource(*fieldIter());
|
||||||
@ -80,6 +83,7 @@ void MapLagrangianFields
|
|||||||
),
|
),
|
||||||
addParticles.size()
|
addParticles.size()
|
||||||
);
|
);
|
||||||
|
|
||||||
forAll(addParticles, i)
|
forAll(addParticles, i)
|
||||||
{
|
{
|
||||||
fieldTarget[i] = fieldSource[addParticles[i]];
|
fieldTarget[i] = fieldSource[addParticles[i]];
|
||||||
@ -88,6 +92,84 @@ void MapLagrangianFields
|
|||||||
// Write field
|
// Write field
|
||||||
fieldTarget.write();
|
fieldTarget.write();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
IOobjectList fieldFields =
|
||||||
|
objects.lookupClass(IOField<Field<Type> >::typeName);
|
||||||
|
|
||||||
|
forAllIter(IOobjectList, fieldFields, fieldIter)
|
||||||
|
{
|
||||||
|
Info<< " mapping lagrangian fieldField "
|
||||||
|
<< fieldIter()->name() << endl;
|
||||||
|
|
||||||
|
// Read field (does not need mesh)
|
||||||
|
IOField<Field<Type> > fieldSource(*fieldIter());
|
||||||
|
|
||||||
|
// Map - use IOFieldField to automatically write in
|
||||||
|
// compact form for binary format.
|
||||||
|
IOFieldField<Field<Type>, Type> fieldTarget
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
fieldIter()->name(),
|
||||||
|
meshTarget.time().timeName(),
|
||||||
|
cloud::prefix/cloudName,
|
||||||
|
meshTarget,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
addParticles.size()
|
||||||
|
);
|
||||||
|
|
||||||
|
forAll(addParticles, i)
|
||||||
|
{
|
||||||
|
fieldTarget[i] = fieldSource[addParticles[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write field
|
||||||
|
fieldTarget.write();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
IOobjectList fieldFields =
|
||||||
|
objects.lookupClass(IOFieldField<Field<Type>, Type>::typeName);
|
||||||
|
|
||||||
|
forAllIter(IOobjectList, fieldFields, fieldIter)
|
||||||
|
{
|
||||||
|
Info<< " mapping lagrangian fieldField "
|
||||||
|
<< fieldIter()->name() << endl;
|
||||||
|
|
||||||
|
// Read field (does not need mesh)
|
||||||
|
IOFieldField<Field<Type>, Type> fieldSource(*fieldIter());
|
||||||
|
|
||||||
|
// Map
|
||||||
|
IOFieldField<Field<Type>, Type> fieldTarget
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
fieldIter()->name(),
|
||||||
|
meshTarget.time().timeName(),
|
||||||
|
cloud::prefix/cloudName,
|
||||||
|
meshTarget,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
addParticles.size()
|
||||||
|
);
|
||||||
|
|
||||||
|
forAll(addParticles, i)
|
||||||
|
{
|
||||||
|
fieldTarget[i] = fieldSource[addParticles[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write field
|
||||||
|
fieldTarget.write();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -38,12 +38,13 @@ static const scalar perturbFactor = 1E-6;
|
|||||||
|
|
||||||
// Special version of findCell that generates a cell guaranteed to be
|
// Special version of findCell that generates a cell guaranteed to be
|
||||||
// compatible with tracking.
|
// compatible with tracking.
|
||||||
static label findCell(const meshSearch& meshSearcher, const point& pt)
|
static label findCell(const Cloud<passiveParticle>& cloud, const point& pt)
|
||||||
{
|
{
|
||||||
const polyMesh& mesh = meshSearcher.mesh();
|
label cellI = -1;
|
||||||
|
label tetFaceI = -1;
|
||||||
|
label tetPtI = -1;
|
||||||
|
|
||||||
// Use tracking to find cell containing pt
|
cloud.findCellFacePt(pt, cellI, tetFaceI, tetPtI);
|
||||||
label cellI = meshSearcher.findCell(pt);
|
|
||||||
|
|
||||||
if (cellI >= 0)
|
if (cellI >= 0)
|
||||||
{
|
{
|
||||||
@ -54,16 +55,24 @@ static label findCell(const meshSearch& meshSearcher, const point& pt)
|
|||||||
// See if particle on face by finding nearest face and shifting
|
// See if particle on face by finding nearest face and shifting
|
||||||
// particle.
|
// particle.
|
||||||
|
|
||||||
|
const polyMesh& mesh = cloud.pMesh();
|
||||||
|
|
||||||
|
meshSearch meshSearcher(mesh, false);
|
||||||
|
|
||||||
label faceI = meshSearcher.findNearestBoundaryFace(pt);
|
label faceI = meshSearcher.findNearestBoundaryFace(pt);
|
||||||
|
|
||||||
if (faceI >= 0)
|
if (faceI >= 0)
|
||||||
{
|
{
|
||||||
const point& cc = mesh.cellCentres()[mesh.faceOwner()[faceI]];
|
const point& cc = mesh.cellCentres()[mesh.faceOwner()[faceI]];
|
||||||
|
|
||||||
const point perturbPt = (1-perturbFactor)*pt+perturbFactor*cc;
|
const point perturbPt = (1-perturbFactor)*pt+perturbFactor*cc;
|
||||||
|
|
||||||
return meshSearcher.findCell(perturbPt);
|
cloud.findCellFacePt(perturbPt, cellI, tetFaceI, tetPtI);
|
||||||
|
|
||||||
|
return cellI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,8 +216,6 @@ void mapLagrangian(const meshToMesh& meshToMeshInterp)
|
|||||||
|
|
||||||
if (unmappedSource.size())
|
if (unmappedSource.size())
|
||||||
{
|
{
|
||||||
meshSearch targetSearcher(meshTarget, false);
|
|
||||||
|
|
||||||
sourceParticleI = 0;
|
sourceParticleI = 0;
|
||||||
|
|
||||||
forAllIter(Cloud<passiveParticle>, sourceParcels, iter)
|
forAllIter(Cloud<passiveParticle>, sourceParcels, iter)
|
||||||
@ -216,7 +223,7 @@ void mapLagrangian(const meshToMesh& meshToMeshInterp)
|
|||||||
if (unmappedSource.found(sourceParticleI))
|
if (unmappedSource.found(sourceParticleI))
|
||||||
{
|
{
|
||||||
label targetCell =
|
label targetCell =
|
||||||
findCell(targetSearcher, iter().position());
|
findCell(targetParcels, iter().position());
|
||||||
|
|
||||||
if (targetCell >= 0)
|
if (targetCell >= 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -35,7 +35,6 @@ Description
|
|||||||
#include "IOdictionary.H"
|
#include "IOdictionary.H"
|
||||||
#include "boundBox.H"
|
#include "boundBox.H"
|
||||||
#include "indexedOctree.H"
|
#include "indexedOctree.H"
|
||||||
#include "octree.H"
|
|
||||||
#include "treeDataTriSurface.H"
|
#include "treeDataTriSurface.H"
|
||||||
#include "Random.H"
|
#include "Random.H"
|
||||||
|
|
||||||
|
|||||||
@ -780,6 +780,7 @@ DebugSwitches
|
|||||||
syringePressure 0;
|
syringePressure 0;
|
||||||
tensorAverageField 0;
|
tensorAverageField 0;
|
||||||
tensorField 0;
|
tensorField 0;
|
||||||
|
tetDecomposedPolyMesh 0;
|
||||||
thermoCloud 0;
|
thermoCloud 0;
|
||||||
thermophysicalFunction 0;
|
thermophysicalFunction 0;
|
||||||
time 0;
|
time 0;
|
||||||
|
|||||||
@ -20,8 +20,6 @@ Pstream/Allwmake
|
|||||||
OSspecific/$WM_OSTYPE/Allwmake
|
OSspecific/$WM_OSTYPE/Allwmake
|
||||||
wmake libso OpenFOAM
|
wmake libso OpenFOAM
|
||||||
|
|
||||||
wmake libso lagrangian/basic
|
|
||||||
|
|
||||||
wmake libso fileFormats
|
wmake libso fileFormats
|
||||||
wmake libso edgeMesh
|
wmake libso edgeMesh
|
||||||
wmake libso surfMesh
|
wmake libso surfMesh
|
||||||
@ -33,6 +31,7 @@ parallel/decompose/AllwmakeLnInclude
|
|||||||
dummyThirdParty/Allwmake
|
dummyThirdParty/Allwmake
|
||||||
|
|
||||||
wmake libso meshTools
|
wmake libso meshTools
|
||||||
|
wmake libso lagrangian/basic
|
||||||
wmake libso finiteVolume
|
wmake libso finiteVolume
|
||||||
wmake libso genericPatchFields
|
wmake libso genericPatchFields
|
||||||
|
|
||||||
|
|||||||
@ -365,6 +365,8 @@ $(globalMeshData)/globalPoints.C
|
|||||||
$(globalMeshData)/globalIndex.C
|
$(globalMeshData)/globalIndex.C
|
||||||
|
|
||||||
$(polyMesh)/syncTools/syncTools.C
|
$(polyMesh)/syncTools/syncTools.C
|
||||||
|
$(polyMesh)/polyMeshTetDecomposition/polyMeshTetDecomposition.C
|
||||||
|
$(polyMesh)/polyMeshTetDecomposition/tetIndices.C
|
||||||
|
|
||||||
zone = $(polyMesh)/zones/zone
|
zone = $(polyMesh)/zones/zone
|
||||||
$(zone)/zone.C
|
$(zone)/zone.C
|
||||||
|
|||||||
@ -33,6 +33,7 @@ License
|
|||||||
#include "processorPolyPatch.H"
|
#include "processorPolyPatch.H"
|
||||||
#include "OSspecific.H"
|
#include "OSspecific.H"
|
||||||
#include "demandDrivenData.H"
|
#include "demandDrivenData.H"
|
||||||
|
#include "polyMeshTetDecomposition.H"
|
||||||
|
|
||||||
#include "pointMesh.H"
|
#include "pointMesh.H"
|
||||||
|
|
||||||
@ -204,6 +205,7 @@ Foam::polyMesh::polyMesh(const IOobject& io)
|
|||||||
bounds_(points_),
|
bounds_(points_),
|
||||||
geometricD_(Vector<label>::zero),
|
geometricD_(Vector<label>::zero),
|
||||||
solutionD_(Vector<label>::zero),
|
solutionD_(Vector<label>::zero),
|
||||||
|
tetBasePtIsPtr_(NULL),
|
||||||
pointZones_
|
pointZones_
|
||||||
(
|
(
|
||||||
IOobject
|
IOobject
|
||||||
@ -392,6 +394,7 @@ Foam::polyMesh::polyMesh
|
|||||||
bounds_(points_, syncPar),
|
bounds_(points_, syncPar),
|
||||||
geometricD_(Vector<label>::zero),
|
geometricD_(Vector<label>::zero),
|
||||||
solutionD_(Vector<label>::zero),
|
solutionD_(Vector<label>::zero),
|
||||||
|
tetBasePtIsPtr_(NULL),
|
||||||
pointZones_
|
pointZones_
|
||||||
(
|
(
|
||||||
IOobject
|
IOobject
|
||||||
@ -548,6 +551,7 @@ Foam::polyMesh::polyMesh
|
|||||||
bounds_(points_, syncPar),
|
bounds_(points_, syncPar),
|
||||||
geometricD_(Vector<label>::zero),
|
geometricD_(Vector<label>::zero),
|
||||||
solutionD_(Vector<label>::zero),
|
solutionD_(Vector<label>::zero),
|
||||||
|
tetBasePtIsPtr_(NULL),
|
||||||
pointZones_
|
pointZones_
|
||||||
(
|
(
|
||||||
IOobject
|
IOobject
|
||||||
@ -847,6 +851,28 @@ Foam::label Foam::polyMesh::nSolutionD() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::labelList& Foam::polyMesh::tetBasePtIs() const
|
||||||
|
{
|
||||||
|
if (!tetBasePtIsPtr_)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
WarningIn("const labelList& polyMesh::tetBasePtIs() const")
|
||||||
|
<< "Tet base point indices not available. "
|
||||||
|
<< "Forcing storage of base points."
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
tetBasePtIsPtr_ = new labelList
|
||||||
|
(
|
||||||
|
polyMeshTetDecomposition::findFaceBasePts(*this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *tetBasePtIsPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add boundary patches. Constructor helper
|
// Add boundary patches. Constructor helper
|
||||||
void Foam::polyMesh::addPatches
|
void Foam::polyMesh::addPatches
|
||||||
(
|
(
|
||||||
|
|||||||
@ -62,6 +62,7 @@ namespace Foam
|
|||||||
|
|
||||||
class globalMeshData;
|
class globalMeshData;
|
||||||
class mapPolyMesh;
|
class mapPolyMesh;
|
||||||
|
class polyMeshTetDecomposition;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class polyMesh Declaration
|
Class polyMesh Declaration
|
||||||
@ -127,6 +128,9 @@ private:
|
|||||||
// defined according to the presence of empty patches
|
// defined according to the presence of empty patches
|
||||||
mutable Vector<label> solutionD_;
|
mutable Vector<label> solutionD_;
|
||||||
|
|
||||||
|
//- Base point for face decomposition into tets
|
||||||
|
mutable labelList* tetBasePtIsPtr_;
|
||||||
|
|
||||||
|
|
||||||
// Zoning information
|
// Zoning information
|
||||||
|
|
||||||
@ -356,6 +360,9 @@ public:
|
|||||||
//- Return the number of valid solved-for dimensions in the mesh
|
//- Return the number of valid solved-for dimensions in the mesh
|
||||||
label nSolutionD() const;
|
label nSolutionD() const;
|
||||||
|
|
||||||
|
//- Return the tetBasePtIs
|
||||||
|
const labelList& tetBasePtIs() const;
|
||||||
|
|
||||||
//- Return point zone mesh
|
//- Return point zone mesh
|
||||||
const pointZoneMesh& pointZones() const
|
const pointZoneMesh& pointZones() const
|
||||||
{
|
{
|
||||||
|
|||||||
@ -71,6 +71,9 @@ void Foam::polyMesh::clearGeom()
|
|||||||
geometricD_ = Vector<label>::zero;
|
geometricD_ = Vector<label>::zero;
|
||||||
solutionD_ = Vector<label>::zero;
|
solutionD_ = Vector<label>::zero;
|
||||||
|
|
||||||
|
// Remove the stored tet base points
|
||||||
|
deleteDemandDrivenData(tetBasePtIsPtr_);
|
||||||
|
|
||||||
pointMesh::Delete(*this);
|
pointMesh::Delete(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -503,6 +503,7 @@ Foam::polyMesh::polyMesh
|
|||||||
bounds_(points_, syncPar),
|
bounds_(points_, syncPar),
|
||||||
geometricD_(Vector<label>::zero),
|
geometricD_(Vector<label>::zero),
|
||||||
solutionD_(Vector<label>::zero),
|
solutionD_(Vector<label>::zero),
|
||||||
|
tetBasePtIsPtr_(NULL),
|
||||||
pointZones_
|
pointZones_
|
||||||
(
|
(
|
||||||
IOobject
|
IOobject
|
||||||
@ -775,6 +776,7 @@ Foam::polyMesh::polyMesh
|
|||||||
bounds_(points_, syncPar),
|
bounds_(points_, syncPar),
|
||||||
geometricD_(Vector<label>::zero),
|
geometricD_(Vector<label>::zero),
|
||||||
solutionD_(Vector<label>::zero),
|
solutionD_(Vector<label>::zero),
|
||||||
|
tetBasePtIsPtr_(NULL),
|
||||||
pointZones_
|
pointZones_
|
||||||
(
|
(
|
||||||
IOobject
|
IOobject
|
||||||
|
|||||||
@ -0,0 +1,627 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2010-2010 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 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "polyMeshTetDecomposition.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::scalar Foam::polyMeshTetDecomposition::minTetQuality = 1e-9;
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::label Foam::polyMeshTetDecomposition::findSharedBasePoint
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
label fI,
|
||||||
|
const point& nCc,
|
||||||
|
scalar tol,
|
||||||
|
bool report
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const faceList& pFaces = mesh.faces();
|
||||||
|
const pointField& pPts = mesh.points();
|
||||||
|
const vectorField& pC = mesh.cellCentres();
|
||||||
|
const labelList& pOwner = mesh.faceOwner();
|
||||||
|
|
||||||
|
const face& f = pFaces[fI];
|
||||||
|
|
||||||
|
label oCI = pOwner[fI];
|
||||||
|
|
||||||
|
const point& oCc = pC[oCI];
|
||||||
|
|
||||||
|
forAll(f, faceBasePtI)
|
||||||
|
{
|
||||||
|
scalar thisBaseMinTetQuality = VGREAT;
|
||||||
|
|
||||||
|
const point& tetBasePt = pPts[f[faceBasePtI]];
|
||||||
|
|
||||||
|
for (label tetPtI = 1; tetPtI < f.size() - 1; tetPtI++)
|
||||||
|
{
|
||||||
|
label facePtI = (tetPtI + faceBasePtI) % f.size();
|
||||||
|
label otherFacePtI = f.fcIndex(facePtI);
|
||||||
|
|
||||||
|
List<scalar> tetQualities(2, 0.0);
|
||||||
|
|
||||||
|
{
|
||||||
|
// owner cell tet
|
||||||
|
label ptAI = f[facePtI];
|
||||||
|
label ptBI = f[otherFacePtI];
|
||||||
|
|
||||||
|
const point& pA = pPts[ptAI];
|
||||||
|
const point& pB = pPts[ptBI];
|
||||||
|
|
||||||
|
tetPointRef tet(oCc, tetBasePt, pA, pB);
|
||||||
|
|
||||||
|
tetQualities[0] = tet.quality();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// neighbour cell tet
|
||||||
|
label ptAI = f[otherFacePtI];
|
||||||
|
label ptBI = f[facePtI];
|
||||||
|
|
||||||
|
const point& pA = pPts[ptAI];
|
||||||
|
const point& pB = pPts[ptBI];
|
||||||
|
|
||||||
|
tetPointRef tet(nCc, tetBasePt, pA, pB);
|
||||||
|
|
||||||
|
tetQualities[1] = tet.quality();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (min(tetQualities) < thisBaseMinTetQuality)
|
||||||
|
{
|
||||||
|
thisBaseMinTetQuality = min(tetQualities);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thisBaseMinTetQuality > tol)
|
||||||
|
{
|
||||||
|
return faceBasePtI;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a base point hasn't triggered a return by now, then there is
|
||||||
|
// non that can produce a good decomposition
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label Foam::polyMeshTetDecomposition::findSharedBasePoint
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
label fI,
|
||||||
|
scalar tol,
|
||||||
|
bool report
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return findSharedBasePoint
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
fI,
|
||||||
|
mesh.cellCentres()[mesh.faceNeighbour()[fI]],
|
||||||
|
tol,
|
||||||
|
report
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label Foam::polyMeshTetDecomposition::findBasePoint
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
label fI,
|
||||||
|
scalar tol,
|
||||||
|
bool report
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const faceList& pFaces = mesh.faces();
|
||||||
|
const pointField& pPts = mesh.points();
|
||||||
|
const vectorField& pC = mesh.cellCentres();
|
||||||
|
const labelList& pOwner = mesh.faceOwner();
|
||||||
|
|
||||||
|
const face& f = pFaces[fI];
|
||||||
|
|
||||||
|
label cI = pOwner[fI];
|
||||||
|
|
||||||
|
bool own = (pOwner[fI] == cI);
|
||||||
|
|
||||||
|
const point& cC = pC[cI];
|
||||||
|
|
||||||
|
forAll(f, faceBasePtI)
|
||||||
|
{
|
||||||
|
scalar thisBaseMinTetQuality = VGREAT;
|
||||||
|
|
||||||
|
const point& tetBasePt = pPts[f[faceBasePtI]];
|
||||||
|
|
||||||
|
for (label tetPtI = 1; tetPtI < f.size() - 1; tetPtI++)
|
||||||
|
{
|
||||||
|
label facePtI = (tetPtI + faceBasePtI) % f.size();
|
||||||
|
label otherFacePtI = f.fcIndex(facePtI);
|
||||||
|
|
||||||
|
label ptAI = -1;
|
||||||
|
label ptBI = -1;
|
||||||
|
|
||||||
|
if (own)
|
||||||
|
{
|
||||||
|
ptAI = f[facePtI];
|
||||||
|
ptBI = f[otherFacePtI];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptAI = f[otherFacePtI];
|
||||||
|
ptBI = f[facePtI];
|
||||||
|
}
|
||||||
|
|
||||||
|
const point& pA = pPts[ptAI];
|
||||||
|
const point& pB = pPts[ptBI];
|
||||||
|
|
||||||
|
tetPointRef tet(cC, tetBasePt, pA, pB);
|
||||||
|
|
||||||
|
scalar tetQuality = tet.quality();
|
||||||
|
|
||||||
|
if (tetQuality < thisBaseMinTetQuality)
|
||||||
|
{
|
||||||
|
thisBaseMinTetQuality = tetQuality;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (thisBaseMinTetQuality > tol)
|
||||||
|
{
|
||||||
|
return faceBasePtI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a base point hasn't triggered a return by now, then there is
|
||||||
|
// non that can produce a good decomposition
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::labelList Foam::polyMeshTetDecomposition::findFaceBasePts
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
scalar tol,
|
||||||
|
bool report
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const labelList& pOwner = mesh.faceOwner();
|
||||||
|
|
||||||
|
// Find a suitable base point for each face, considering both
|
||||||
|
// cells for interface faces or those on coupled patches
|
||||||
|
|
||||||
|
labelList tetBasePtIs(mesh.nFaces(), -1);
|
||||||
|
|
||||||
|
label nInternalFaces = mesh.nInternalFaces();
|
||||||
|
|
||||||
|
for (label fI = 0; fI < nInternalFaces; fI++)
|
||||||
|
{
|
||||||
|
tetBasePtIs[fI] = findSharedBasePoint(mesh, fI, tol, report);
|
||||||
|
}
|
||||||
|
|
||||||
|
pointField neighbourCellCentres(mesh.nFaces() - nInternalFaces);
|
||||||
|
|
||||||
|
for(label faceI = nInternalFaces; faceI < mesh.nFaces(); faceI++)
|
||||||
|
{
|
||||||
|
neighbourCellCentres[faceI - nInternalFaces] =
|
||||||
|
mesh.cellCentres()[pOwner[faceI]];
|
||||||
|
}
|
||||||
|
|
||||||
|
syncTools::swapBoundaryFacePositions(mesh, neighbourCellCentres);
|
||||||
|
|
||||||
|
const polyBoundaryMesh& patches = mesh.boundaryMesh();
|
||||||
|
|
||||||
|
SubList<label> boundaryFaceTetBasePtIs
|
||||||
|
(
|
||||||
|
tetBasePtIs,
|
||||||
|
mesh.nFaces() - nInternalFaces,
|
||||||
|
nInternalFaces
|
||||||
|
);
|
||||||
|
|
||||||
|
for
|
||||||
|
(
|
||||||
|
label fI = nInternalFaces, bFI = 0;
|
||||||
|
fI < mesh.nFaces();
|
||||||
|
fI++, bFI++
|
||||||
|
)
|
||||||
|
{
|
||||||
|
label patchI =
|
||||||
|
mesh.boundaryMesh().patchID()[bFI];
|
||||||
|
|
||||||
|
if (patches[patchI].coupled())
|
||||||
|
{
|
||||||
|
const coupledPolyPatch& pp =
|
||||||
|
refCast<const coupledPolyPatch>(patches[patchI]);
|
||||||
|
|
||||||
|
if (pp.owner())
|
||||||
|
{
|
||||||
|
boundaryFaceTetBasePtIs[bFI] = findSharedBasePoint
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
fI,
|
||||||
|
neighbourCellCentres[bFI],
|
||||||
|
tol,
|
||||||
|
report
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Assign -2, to distinguish from a failed base point
|
||||||
|
// find, which returns -1.
|
||||||
|
boundaryFaceTetBasePtIs[bFI] = -2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boundaryFaceTetBasePtIs[bFI] = findBasePoint
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
fI,
|
||||||
|
tol,
|
||||||
|
report
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// maxEqOp will replace the -2 values on the neighbour patches
|
||||||
|
// with the result from the owner base point find.
|
||||||
|
|
||||||
|
syncTools::syncBoundaryFaceList
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
boundaryFaceTetBasePtIs,
|
||||||
|
maxEqOp<label>()
|
||||||
|
);
|
||||||
|
|
||||||
|
for
|
||||||
|
(
|
||||||
|
label fI = nInternalFaces, bFI = 0;
|
||||||
|
fI < mesh.nFaces();
|
||||||
|
fI++, bFI++
|
||||||
|
)
|
||||||
|
{
|
||||||
|
label& bFTetBasePtI = boundaryFaceTetBasePtIs[bFI];
|
||||||
|
|
||||||
|
if (bFTetBasePtI == -2)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"Foam::labelList"
|
||||||
|
"Foam::polyMeshTetDecomposition::findFaceBasePts"
|
||||||
|
"("
|
||||||
|
"const polyMesh& mesh, "
|
||||||
|
"scalar tol, "
|
||||||
|
"bool report"
|
||||||
|
")"
|
||||||
|
)
|
||||||
|
<< "Coupled face base point exchange failure for face "
|
||||||
|
<< fI
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bFTetBasePtI < 1)
|
||||||
|
{
|
||||||
|
// If the base point is -1, it should be left as such to
|
||||||
|
// indicate a problem, if it is 0, then no action is required.
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
label patchI = mesh.boundaryMesh().patchID()[bFI];
|
||||||
|
|
||||||
|
if (patches[patchI].coupled())
|
||||||
|
{
|
||||||
|
const coupledPolyPatch& pp =
|
||||||
|
refCast<const coupledPolyPatch>(patches[patchI]);
|
||||||
|
|
||||||
|
// Calculated base points on coupled faces are those of
|
||||||
|
// the owner patch face. They need to be reindexed to for
|
||||||
|
// the non-owner face, which has the opposite order.
|
||||||
|
|
||||||
|
// So, for fPtI_o != 0, fPtI_n = f.size() - fPtI_o
|
||||||
|
|
||||||
|
// i.e.:
|
||||||
|
|
||||||
|
// owner coupledPolyPatch face
|
||||||
|
// face (a b c d e f)
|
||||||
|
// fPtI 0 1 2 3 4 5
|
||||||
|
// +
|
||||||
|
// #
|
||||||
|
|
||||||
|
// neighbour coupledPolyPatch face
|
||||||
|
// face (a f e d c b)
|
||||||
|
// fPtI 0 1 2 3 4 5
|
||||||
|
// +
|
||||||
|
// #
|
||||||
|
// +: 6 - 1 = 5
|
||||||
|
// #: 6 - 2 = 4
|
||||||
|
|
||||||
|
if (!pp.owner())
|
||||||
|
{
|
||||||
|
bFTetBasePtI = mesh.faces()[fI].size() - bFTetBasePtI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tetBasePtIs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::polyMeshTetDecomposition::checkFaceTets
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
scalar tol,
|
||||||
|
const bool report,
|
||||||
|
labelHashSet* setPtr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const labelList& own = mesh.faceOwner();
|
||||||
|
const labelList& nei = mesh.faceNeighbour();
|
||||||
|
const polyBoundaryMesh& patches = mesh.boundaryMesh();
|
||||||
|
|
||||||
|
const vectorField& cc = mesh.cellCentres();
|
||||||
|
const vectorField& fc = mesh.faceCentres();
|
||||||
|
|
||||||
|
// Calculate coupled cell centre
|
||||||
|
pointField neiCc(mesh.nFaces() - mesh.nInternalFaces());
|
||||||
|
|
||||||
|
for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++)
|
||||||
|
{
|
||||||
|
neiCc[faceI - mesh.nInternalFaces()] = cc[own[faceI]];
|
||||||
|
}
|
||||||
|
|
||||||
|
syncTools::swapBoundaryFacePositions(mesh, neiCc);
|
||||||
|
|
||||||
|
const faceList& fcs = mesh.faces();
|
||||||
|
|
||||||
|
const pointField& p = mesh.points();
|
||||||
|
|
||||||
|
label nErrorTets = 0;
|
||||||
|
|
||||||
|
forAll(fcs, faceI)
|
||||||
|
{
|
||||||
|
const face& f = fcs[faceI];
|
||||||
|
|
||||||
|
forAll(f, fPtI)
|
||||||
|
{
|
||||||
|
scalar tetQual = tetPointRef
|
||||||
|
(
|
||||||
|
p[f[fPtI]],
|
||||||
|
p[f.nextLabel(fPtI)],
|
||||||
|
fc[faceI],
|
||||||
|
cc[own[faceI]]
|
||||||
|
).quality();
|
||||||
|
|
||||||
|
if (tetQual > -tol)
|
||||||
|
{
|
||||||
|
if (setPtr)
|
||||||
|
{
|
||||||
|
setPtr->insert(faceI);
|
||||||
|
}
|
||||||
|
|
||||||
|
nErrorTets++;
|
||||||
|
break; // no need to check other tets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh.isInternalFace(faceI))
|
||||||
|
{
|
||||||
|
// Create the neighbour tet - it will have positive volume
|
||||||
|
const face& f = fcs[faceI];
|
||||||
|
|
||||||
|
forAll(f, fPtI)
|
||||||
|
{
|
||||||
|
scalar tetQual = tetPointRef
|
||||||
|
(
|
||||||
|
p[f[fPtI]],
|
||||||
|
p[f.nextLabel(fPtI)],
|
||||||
|
fc[faceI],
|
||||||
|
cc[nei[faceI]]
|
||||||
|
).quality();
|
||||||
|
|
||||||
|
if (tetQual < tol)
|
||||||
|
{
|
||||||
|
if (setPtr)
|
||||||
|
{
|
||||||
|
setPtr->insert(faceI);
|
||||||
|
}
|
||||||
|
|
||||||
|
nErrorTets++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findSharedBasePoint(mesh, faceI, tol, report) == -1)
|
||||||
|
{
|
||||||
|
if (setPtr)
|
||||||
|
{
|
||||||
|
setPtr->insert(faceI);
|
||||||
|
}
|
||||||
|
|
||||||
|
nErrorTets++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label patchI = patches.patchID()[faceI - mesh.nInternalFaces()];
|
||||||
|
|
||||||
|
if (patches[patchI].coupled())
|
||||||
|
{
|
||||||
|
if
|
||||||
|
(
|
||||||
|
findSharedBasePoint
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
faceI,
|
||||||
|
neiCc[faceI - mesh.nInternalFaces()],
|
||||||
|
tol,
|
||||||
|
report
|
||||||
|
) == -1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (setPtr)
|
||||||
|
{
|
||||||
|
setPtr->insert(faceI);
|
||||||
|
}
|
||||||
|
|
||||||
|
nErrorTets++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (findBasePoint(mesh, faceI, tol, report) == -1)
|
||||||
|
{
|
||||||
|
if (setPtr)
|
||||||
|
{
|
||||||
|
setPtr->insert(faceI);
|
||||||
|
}
|
||||||
|
|
||||||
|
nErrorTets++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce(nErrorTets, sumOp<label>());
|
||||||
|
|
||||||
|
if (nErrorTets > 0)
|
||||||
|
{
|
||||||
|
if (report)
|
||||||
|
{
|
||||||
|
Info<< " ***Error in face tets: "
|
||||||
|
<< nErrorTets << " faces with low quality or negative volume "
|
||||||
|
<< "decomposition tets." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (report)
|
||||||
|
{
|
||||||
|
Info<< " Face tets OK." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::List<Foam::tetIndices> Foam::polyMeshTetDecomposition::faceTetIndices
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
label fI,
|
||||||
|
label cI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const faceList& pFaces = mesh.faces();
|
||||||
|
const labelList& pOwner = mesh.faceOwner();
|
||||||
|
|
||||||
|
const face& f = pFaces[fI];
|
||||||
|
|
||||||
|
label nTets = f.size() - 2;
|
||||||
|
|
||||||
|
List<tetIndices> faceTets(nTets);
|
||||||
|
|
||||||
|
bool own = (pOwner[fI] == cI);
|
||||||
|
|
||||||
|
label tetBasePtI = mesh.tetBasePtIs()[fI];
|
||||||
|
|
||||||
|
if (tetBasePtI == -1)
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"Foam::List<Foam::FixedList<Foam::label, 4> >"
|
||||||
|
"Foam::Cloud<ParticleType>::"
|
||||||
|
"faceTetIndices(label fI, label cI) const"
|
||||||
|
)
|
||||||
|
<< "No base point for face " << fI << ", " << f
|
||||||
|
<< ", produces a valid tet decomposition."
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (label tetPtI = 1; tetPtI < f.size() - 1; tetPtI++)
|
||||||
|
{
|
||||||
|
tetIndices& faceTetIs = faceTets[tetPtI - 1];
|
||||||
|
|
||||||
|
label facePtI = (tetPtI + tetBasePtI) % f.size();
|
||||||
|
label otherFacePtI = f.fcIndex(facePtI);
|
||||||
|
|
||||||
|
faceTetIs.cell() = cI;
|
||||||
|
|
||||||
|
faceTetIs.face() = fI;
|
||||||
|
|
||||||
|
faceTetIs.faceBasePt() = tetBasePtI;
|
||||||
|
|
||||||
|
if (own)
|
||||||
|
{
|
||||||
|
faceTetIs.facePtA() = facePtI;
|
||||||
|
faceTetIs.facePtB() = otherFacePtI;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
faceTetIs.facePtA() = otherFacePtI;
|
||||||
|
faceTetIs.facePtB() = facePtI;
|
||||||
|
}
|
||||||
|
|
||||||
|
faceTetIs.tetPt() = tetPtI;
|
||||||
|
}
|
||||||
|
|
||||||
|
return faceTets;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::List<Foam::tetIndices> Foam::polyMeshTetDecomposition::cellTetIndices
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
label cI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const faceList& pFaces = mesh.faces();
|
||||||
|
const cellList& pCells = mesh.cells();
|
||||||
|
|
||||||
|
const cell& thisCell = pCells[cI];
|
||||||
|
|
||||||
|
label nTets = 0;
|
||||||
|
|
||||||
|
forAll(thisCell, cFI)
|
||||||
|
{
|
||||||
|
nTets += pFaces[thisCell[cFI]].size() - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicList<tetIndices> cellTets(nTets);
|
||||||
|
|
||||||
|
forAll(thisCell, cFI)
|
||||||
|
{
|
||||||
|
label fI = thisCell[cFI];
|
||||||
|
|
||||||
|
cellTets.append(faceTetIndices(mesh, fI, cI));
|
||||||
|
}
|
||||||
|
|
||||||
|
return cellTets;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,151 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2010-2010 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 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::polyMeshTetDecomposition
|
||||||
|
|
||||||
|
Description
|
||||||
|
Tools for performing the minimum decomposition of faces of the
|
||||||
|
mesh into triangles so that the cells may be tet decomposed.
|
||||||
|
Includes functions for finding variable face starting (base)
|
||||||
|
points on each face to avoid the decomposition of cells into tets
|
||||||
|
that have negative or zero volume.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
polyMeshTetDecomposition.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef polyMeshTetDecomposition_H
|
||||||
|
#define polyMeshTetDecomposition_H
|
||||||
|
|
||||||
|
#include "polyMesh.H"
|
||||||
|
#include "coupledPolyPatch.H"
|
||||||
|
#include "syncTools.H"
|
||||||
|
#include "tetPointRef.H"
|
||||||
|
#include "tetIndices.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class polyMeshTetDecomposition Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class polyMeshTetDecomposition
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Static data members
|
||||||
|
|
||||||
|
//- Minimum tetrahedron quality
|
||||||
|
static const scalar minTetQuality;
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Find the first suitable base point to use for a minimum
|
||||||
|
// triangle decomposition of the face, suiting owner and
|
||||||
|
// neighbour cells. Finds the first base point on the face
|
||||||
|
// whose worst quality tet from either cell is better than
|
||||||
|
// tolerance. Neighbour cell centre supplied. For coupled
|
||||||
|
// patches.
|
||||||
|
static label findSharedBasePoint
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
label fI,
|
||||||
|
const point& nCc,
|
||||||
|
scalar tol,
|
||||||
|
bool report = false
|
||||||
|
);
|
||||||
|
|
||||||
|
//- As for findSharedBasePoint, but using neighbour cell
|
||||||
|
// centre from the mesh. For internal faces.
|
||||||
|
static label findSharedBasePoint
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
label fI,
|
||||||
|
scalar tol,
|
||||||
|
bool report = false
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Find the base point to use for a minimum triangle
|
||||||
|
// decomposition of the face, using only the owner
|
||||||
|
// information. For non-coupled boundary faces.
|
||||||
|
static label findBasePoint
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
label fI,
|
||||||
|
scalar tol,
|
||||||
|
bool report = false
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Find a suitable base point for each face for decomposition
|
||||||
|
// into tets
|
||||||
|
static labelList findFaceBasePts
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
scalar tol = minTetQuality,
|
||||||
|
bool report = false
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Check face-decomposition tet volume
|
||||||
|
static bool checkFaceTets
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
scalar tol = minTetQuality,
|
||||||
|
const bool report = false,
|
||||||
|
labelHashSet* setPtr = NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Return the tet decomposition of the given face, with
|
||||||
|
// respect to the given cell
|
||||||
|
static List<tetIndices> faceTetIndices
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
label fI,
|
||||||
|
label cI
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Return the tet decomposition of the given cell, see
|
||||||
|
// findFacePt for the meaning of the indices
|
||||||
|
static List<tetIndices> cellTetIndices
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
label cI
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,148 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2010-2010 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 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "tetIndices.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::tetIndices::tetIndices()
|
||||||
|
:
|
||||||
|
cellI_(-1),
|
||||||
|
faceI_(-1),
|
||||||
|
faceBasePtI_(-1),
|
||||||
|
facePtAI_(-1),
|
||||||
|
facePtBI_(-1),
|
||||||
|
tetPtI_(-1)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tetIndices::tetIndices
|
||||||
|
(
|
||||||
|
label cellI,
|
||||||
|
label faceI,
|
||||||
|
label faceBasePtI,
|
||||||
|
label facePtAI,
|
||||||
|
label facePtBI,
|
||||||
|
label tetPtI
|
||||||
|
)
|
||||||
|
:
|
||||||
|
cellI_(cellI),
|
||||||
|
faceI_(faceI),
|
||||||
|
faceBasePtI_(faceBasePtI),
|
||||||
|
facePtAI_(facePtAI),
|
||||||
|
facePtBI_(facePtBI),
|
||||||
|
tetPtI_(tetPtI)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tetIndices::tetIndices
|
||||||
|
(
|
||||||
|
label cellI,
|
||||||
|
label faceI,
|
||||||
|
label tetPtI,
|
||||||
|
const polyMesh& mesh
|
||||||
|
)
|
||||||
|
:
|
||||||
|
cellI_(cellI),
|
||||||
|
faceI_(faceI),
|
||||||
|
faceBasePtI_(-1),
|
||||||
|
facePtAI_(-1),
|
||||||
|
facePtBI_(-1),
|
||||||
|
tetPtI_(tetPtI)
|
||||||
|
{
|
||||||
|
const faceList& pFaces = mesh.faces();
|
||||||
|
const labelList& pOwner = mesh.faceOwner();
|
||||||
|
|
||||||
|
const Foam::face& f = pFaces[faceI_];
|
||||||
|
|
||||||
|
bool own = (pOwner[faceI_] == cellI_);
|
||||||
|
|
||||||
|
faceBasePtI_ = mesh.tetBasePtIs()[faceI_];
|
||||||
|
|
||||||
|
label facePtI = (tetPtI_ + faceBasePtI_) % f.size();
|
||||||
|
label otherFacePtI = f.fcIndex(facePtI);
|
||||||
|
|
||||||
|
if (own)
|
||||||
|
{
|
||||||
|
facePtAI_ = facePtI;
|
||||||
|
facePtBI_ = otherFacePtI;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
facePtAI_ = otherFacePtI;
|
||||||
|
facePtBI_ = facePtI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::tetIndices::~tetIndices()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::Istream& Foam::operator>>(Istream& is, tetIndices& tI)
|
||||||
|
{
|
||||||
|
is >> tI.cell()
|
||||||
|
>> tI.face()
|
||||||
|
>> tI.faceBasePt()
|
||||||
|
>> tI.facePtA()
|
||||||
|
>> tI.facePtB()
|
||||||
|
>> tI.tetPt();
|
||||||
|
|
||||||
|
// Check state of Istream
|
||||||
|
is.check
|
||||||
|
(
|
||||||
|
"Foam::Istream& Foam::operator>>(Foam::Istream&, Foam::tetIndices&)"
|
||||||
|
);
|
||||||
|
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::Ostream& Foam::operator<<(Ostream& os, const tetIndices& tI)
|
||||||
|
{
|
||||||
|
os << tI.cell() << token::SPACE
|
||||||
|
<< tI.face() << token::SPACE
|
||||||
|
<< tI.faceBasePt() << token::SPACE
|
||||||
|
<< tI.facePtA() << token::SPACE
|
||||||
|
<< tI.facePtB() << token::SPACE
|
||||||
|
<< tI.tetPt() << token::SPACE
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
// Check state of Ostream
|
||||||
|
os.check
|
||||||
|
(
|
||||||
|
"Foam::Ostream& Foam::operator<<(Foam::Ostream&, "
|
||||||
|
"const Foam::tetIndices&)"
|
||||||
|
);
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,201 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2010-2010 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 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::tetIndices
|
||||||
|
|
||||||
|
Description
|
||||||
|
Storage and named access for the indices of a tet which is part of
|
||||||
|
the decomposition of a cell.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
tetIndicesI.H
|
||||||
|
tetIndices.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef tetIndices_H
|
||||||
|
#define tetIndices_H
|
||||||
|
|
||||||
|
#include "label.H"
|
||||||
|
#include "tetPointRef.H"
|
||||||
|
#include "triPointRef.H"
|
||||||
|
#include "polyMesh.H"
|
||||||
|
#include "face.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class tetIndices Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class tetIndices
|
||||||
|
{
|
||||||
|
// Private data
|
||||||
|
|
||||||
|
//- cell that this is a decomposed tet of
|
||||||
|
label cellI_;
|
||||||
|
|
||||||
|
//- face that holds this decomposed tet
|
||||||
|
label faceI_;
|
||||||
|
|
||||||
|
//- base point on the face
|
||||||
|
label faceBasePtI_;
|
||||||
|
|
||||||
|
//- point on the face such that the right-hand circulation
|
||||||
|
// {faceBasePtI_, facePtIA_, facePtBI_}
|
||||||
|
// forms a triangle that points out of the tet
|
||||||
|
label facePtAI_;
|
||||||
|
|
||||||
|
//- point on the face such that the right-hand circulation
|
||||||
|
// {faceBasePtI_, facePtIA_, facePtBI_}
|
||||||
|
// forms a triangle that points out of the tet
|
||||||
|
label facePtBI_;
|
||||||
|
|
||||||
|
//- point on the face, *relative to the base point*, which
|
||||||
|
// characterises this tet on the face.
|
||||||
|
label tetPtI_;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct null
|
||||||
|
tetIndices();
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
tetIndices
|
||||||
|
(
|
||||||
|
label cellI,
|
||||||
|
label faceI,
|
||||||
|
label faceBasePtI,
|
||||||
|
label facePtAI,
|
||||||
|
label facePtBI,
|
||||||
|
label tetPtI
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from cell, face, pt description of tet
|
||||||
|
tetIndices
|
||||||
|
(
|
||||||
|
label cellI,
|
||||||
|
label faceI,
|
||||||
|
label tetPtI,
|
||||||
|
const polyMesh& mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
~tetIndices();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
// Access
|
||||||
|
|
||||||
|
//- Return the cell
|
||||||
|
inline label cell() const;
|
||||||
|
|
||||||
|
//- Return the face
|
||||||
|
inline label face() const;
|
||||||
|
|
||||||
|
//- Return the face base point
|
||||||
|
inline label faceBasePt() const;
|
||||||
|
|
||||||
|
//- Return face point A
|
||||||
|
inline label facePtA() const;
|
||||||
|
|
||||||
|
//- Return face point B
|
||||||
|
inline label facePtB() const;
|
||||||
|
|
||||||
|
//- Return the characterising tetPtI
|
||||||
|
inline label tetPt() const;
|
||||||
|
|
||||||
|
//- Return the geometry corresponding to this tet from the
|
||||||
|
// supplied mesh
|
||||||
|
inline tetPointRef tet(const polyMesh& mesh) const;
|
||||||
|
|
||||||
|
//- Return the geometry corresponding to this tet from the
|
||||||
|
// supplied mesh using the old positions
|
||||||
|
inline tetPointRef oldTet(const polyMesh& mesh) const;
|
||||||
|
|
||||||
|
//- Return the geometry corresponding to the tri on the
|
||||||
|
// mesh face for this tet from the supplied mesh
|
||||||
|
inline triPointRef faceTri(const polyMesh& mesh) const;
|
||||||
|
|
||||||
|
//- Return the geometry corresponding to the tri on the
|
||||||
|
// mesh face for this tet from the supplied mesh using
|
||||||
|
// the old position
|
||||||
|
inline triPointRef oldFaceTri(const polyMesh& mesh) const;
|
||||||
|
|
||||||
|
|
||||||
|
// Edit
|
||||||
|
|
||||||
|
//- Return non-const access to the cell
|
||||||
|
inline label& cell();
|
||||||
|
|
||||||
|
//- Return non-const access to the face
|
||||||
|
inline label& face();
|
||||||
|
|
||||||
|
//- Return non-const access to the face base point
|
||||||
|
inline label& faceBasePt();
|
||||||
|
|
||||||
|
//- Return non-const access to face point A
|
||||||
|
inline label& facePtA();
|
||||||
|
|
||||||
|
//- Return non-const access to face point B
|
||||||
|
inline label& facePtB();
|
||||||
|
|
||||||
|
//- Return non-const access to the characterising tetPtI
|
||||||
|
inline label& tetPt();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Operators
|
||||||
|
|
||||||
|
inline bool operator==(const tetIndices&) const;
|
||||||
|
inline bool operator!=(const tetIndices&) const;
|
||||||
|
|
||||||
|
|
||||||
|
// IOstream Operators
|
||||||
|
|
||||||
|
friend Istream& operator>>(Istream&, tetIndices&);
|
||||||
|
friend Ostream& operator<<(Ostream&, const tetIndices&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#include "tetIndicesI.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,202 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2010-2010 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 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/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::label Foam::tetIndices::cell() const
|
||||||
|
{
|
||||||
|
return cellI_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label Foam::tetIndices::face() const
|
||||||
|
{
|
||||||
|
return faceI_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label Foam::tetIndices::faceBasePt() const
|
||||||
|
{
|
||||||
|
return faceBasePtI_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label Foam::tetIndices::facePtA() const
|
||||||
|
{
|
||||||
|
return facePtAI_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label Foam::tetIndices::facePtB() const
|
||||||
|
{
|
||||||
|
return facePtBI_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label Foam::tetIndices::tetPt() const
|
||||||
|
{
|
||||||
|
return tetPtI_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tetPointRef Foam::tetIndices::tet(const polyMesh& mesh) const
|
||||||
|
{
|
||||||
|
const pointField& pPts = mesh.points();
|
||||||
|
const faceList& pFaces = mesh.faces();
|
||||||
|
const vectorField& pC = mesh.cellCentres();
|
||||||
|
|
||||||
|
const Foam::face& f = pFaces[faceI_];
|
||||||
|
|
||||||
|
return tetPointRef
|
||||||
|
(
|
||||||
|
pC[cellI_],
|
||||||
|
pPts[f[faceBasePtI_]],
|
||||||
|
pPts[f[facePtAI_]],
|
||||||
|
pPts[f[facePtBI_]]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tetPointRef Foam::tetIndices::oldTet(const polyMesh& mesh) const
|
||||||
|
{
|
||||||
|
const pointField& oldPPts = mesh.oldPoints();
|
||||||
|
const faceList& pFaces = mesh.faces();
|
||||||
|
|
||||||
|
// We need to reconstruct the old Cc from oldPoints (it isn't
|
||||||
|
// stored)
|
||||||
|
point oldC = mesh.cells()[cellI_].centre
|
||||||
|
(
|
||||||
|
oldPPts,
|
||||||
|
pFaces
|
||||||
|
);
|
||||||
|
|
||||||
|
const Foam::face& f = pFaces[faceI_];
|
||||||
|
|
||||||
|
return tetPointRef
|
||||||
|
(
|
||||||
|
oldC,
|
||||||
|
oldPPts[f[faceBasePtI_]],
|
||||||
|
oldPPts[f[facePtAI_]],
|
||||||
|
oldPPts[f[facePtBI_]]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::triPointRef Foam::tetIndices::faceTri(const polyMesh& mesh) const
|
||||||
|
{
|
||||||
|
const pointField& pPts = mesh.points();
|
||||||
|
const faceList& pFaces = mesh.faces();
|
||||||
|
|
||||||
|
const Foam::face& f = pFaces[faceI_];
|
||||||
|
|
||||||
|
return triPointRef
|
||||||
|
(
|
||||||
|
pPts[f[faceBasePtI_]],
|
||||||
|
pPts[f[facePtAI_]],
|
||||||
|
pPts[f[facePtBI_]]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::triPointRef Foam::tetIndices::oldFaceTri(const polyMesh& mesh) const
|
||||||
|
{
|
||||||
|
const pointField& oldPPts = mesh.oldPoints();
|
||||||
|
const faceList& pFaces = mesh.faces();
|
||||||
|
|
||||||
|
const Foam::face& f = pFaces[faceI_];
|
||||||
|
|
||||||
|
return triPointRef
|
||||||
|
(
|
||||||
|
oldPPts[f[faceBasePtI_]],
|
||||||
|
oldPPts[f[facePtAI_]],
|
||||||
|
oldPPts[f[facePtBI_]]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label& Foam::tetIndices::cell()
|
||||||
|
{
|
||||||
|
return cellI_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label& Foam::tetIndices::face()
|
||||||
|
{
|
||||||
|
return faceI_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label& Foam::tetIndices::faceBasePt()
|
||||||
|
{
|
||||||
|
return faceBasePtI_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label& Foam::tetIndices::facePtA()
|
||||||
|
{
|
||||||
|
return facePtAI_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label& Foam::tetIndices::facePtB()
|
||||||
|
{
|
||||||
|
return facePtBI_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::label& Foam::tetIndices::tetPt()
|
||||||
|
{
|
||||||
|
return tetPtI_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
inline bool Foam::tetIndices::operator==(const Foam::tetIndices& rhs) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
cell() == rhs.cell()
|
||||||
|
&& face() == rhs.face()
|
||||||
|
&& faceBasePt() == rhs.faceBasePt()
|
||||||
|
&& facePtA() == rhs.facePtA()
|
||||||
|
&& facePtB() == rhs.facePtB()
|
||||||
|
&& tetPt() == rhs.tetPt()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::tetIndices::operator!=(const Foam::tetIndices& rhs) const
|
||||||
|
{
|
||||||
|
return !(*this == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -229,6 +229,19 @@ public:
|
|||||||
|
|
||||||
// Member functions
|
// Member functions
|
||||||
|
|
||||||
|
//- Return true only if this is a parallel run
|
||||||
|
virtual bool coupled() const
|
||||||
|
{
|
||||||
|
if (Pstream::parRun())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//- Return processor number
|
//- Return processor number
|
||||||
int myProcNo() const
|
int myProcNo() const
|
||||||
{
|
{
|
||||||
|
|||||||
@ -66,6 +66,7 @@ SourceFiles
|
|||||||
#include "HashSet.H"
|
#include "HashSet.H"
|
||||||
#include "Map.H"
|
#include "Map.H"
|
||||||
#include "EdgeMap.H"
|
#include "EdgeMap.H"
|
||||||
|
#include "boundBox.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -577,14 +578,6 @@ public:
|
|||||||
labelHashSet* setPtr = NULL
|
labelHashSet* setPtr = NULL
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Check face-decomposition tet volume
|
|
||||||
bool checkFaceTets
|
|
||||||
(
|
|
||||||
const bool report = false,
|
|
||||||
const scalar minTetVol = 0,
|
|
||||||
labelHashSet* setPtr = NULL
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Check face skewness
|
//- Check face skewness
|
||||||
bool checkFaceSkewness
|
bool checkFaceSkewness
|
||||||
(
|
(
|
||||||
|
|||||||
@ -618,114 +618,6 @@ bool Foam::primitiveMesh::checkFacePyramids
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Foam::primitiveMesh::checkFaceTets
|
|
||||||
(
|
|
||||||
const bool report,
|
|
||||||
const scalar minTetVol,
|
|
||||||
labelHashSet* setPtr
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
if (debug)
|
|
||||||
{
|
|
||||||
Info<< "bool primitiveMesh::checkFaceTets("
|
|
||||||
<< "const bool, const scalar, labelHashSet*) const: "
|
|
||||||
<< "checking face orientation" << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check whether face area vector points to the cell with higher label
|
|
||||||
const vectorField& cc = cellCentres();
|
|
||||||
const vectorField& fc = faceCentres();
|
|
||||||
|
|
||||||
const labelList& own = faceOwner();
|
|
||||||
const labelList& nei = faceNeighbour();
|
|
||||||
|
|
||||||
const faceList& fcs = faces();
|
|
||||||
|
|
||||||
const pointField& p = points();
|
|
||||||
|
|
||||||
label nErrorPyrs = 0;
|
|
||||||
|
|
||||||
forAll(fcs, faceI)
|
|
||||||
{
|
|
||||||
// Create the owner tets - they will have negative volume
|
|
||||||
const face& f = fcs[faceI];
|
|
||||||
|
|
||||||
forAll(f, fp)
|
|
||||||
{
|
|
||||||
scalar tetVol = tetPointRef
|
|
||||||
(
|
|
||||||
p[f[fp]],
|
|
||||||
p[f.nextLabel(fp)],
|
|
||||||
fc[faceI],
|
|
||||||
cc[own[faceI]]
|
|
||||||
).mag();
|
|
||||||
|
|
||||||
if (tetVol > -minTetVol)
|
|
||||||
{
|
|
||||||
if (setPtr)
|
|
||||||
{
|
|
||||||
setPtr->insert(faceI);
|
|
||||||
}
|
|
||||||
|
|
||||||
nErrorPyrs++;
|
|
||||||
break; // no need to check other tets
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isInternalFace(faceI))
|
|
||||||
{
|
|
||||||
// Create the neighbour tet - it will have positive volume
|
|
||||||
const face& f = fcs[faceI];
|
|
||||||
|
|
||||||
forAll(f, fp)
|
|
||||||
{
|
|
||||||
scalar tetVol = tetPointRef
|
|
||||||
(
|
|
||||||
p[f[fp]],
|
|
||||||
p[f.nextLabel(fp)],
|
|
||||||
fc[faceI],
|
|
||||||
cc[nei[faceI]]
|
|
||||||
).mag();
|
|
||||||
|
|
||||||
if (tetVol < minTetVol)
|
|
||||||
{
|
|
||||||
if (setPtr)
|
|
||||||
{
|
|
||||||
setPtr->insert(faceI);
|
|
||||||
}
|
|
||||||
|
|
||||||
nErrorPyrs++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reduce(nErrorPyrs, sumOp<label>());
|
|
||||||
|
|
||||||
if (nErrorPyrs > 0)
|
|
||||||
{
|
|
||||||
if (debug || report)
|
|
||||||
{
|
|
||||||
Info<< " ***Error in face tets: "
|
|
||||||
<< nErrorPyrs << " faces have incorrectly oriented face"
|
|
||||||
<< " decomposition triangles." << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (debug || report)
|
|
||||||
{
|
|
||||||
Info<< " Face tets OK." << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Foam::primitiveMesh::checkFaceSkewness
|
bool Foam::primitiveMesh::checkFaceSkewness
|
||||||
(
|
(
|
||||||
const bool report,
|
const bool report,
|
||||||
|
|||||||
@ -32,32 +32,14 @@ License
|
|||||||
// Is the point in the cell bounding box
|
// Is the point in the cell bounding box
|
||||||
bool Foam::primitiveMesh::pointInCellBB(const point& p, label celli) const
|
bool Foam::primitiveMesh::pointInCellBB(const point& p, label celli) const
|
||||||
{
|
{
|
||||||
const pointField& points = this->points();
|
return boundBox
|
||||||
const faceList& f = faces();
|
(
|
||||||
const vectorField& centres = cellCentres();
|
cells()[celli].points
|
||||||
const cellList& cf = cells();
|
(
|
||||||
|
faces(),
|
||||||
labelList cellVertices = cf[celli].labels(f);
|
points()
|
||||||
|
)
|
||||||
vector bbmax = -GREAT*vector::one;
|
).contains(p);
|
||||||
vector bbmin = GREAT*vector::one;
|
|
||||||
|
|
||||||
forAll(cellVertices, vertexI)
|
|
||||||
{
|
|
||||||
bbmax = max(bbmax, points[cellVertices[vertexI]]);
|
|
||||||
bbmin = min(bbmin, points[cellVertices[vertexI]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
scalar distance = mag(centres[celli] - p);
|
|
||||||
|
|
||||||
if ((distance - mag(bbmax - bbmin)) < SMALL)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,6 @@ Description
|
|||||||
#include "triPointRef.H"
|
#include "triPointRef.H"
|
||||||
#include "scalarField.H"
|
#include "scalarField.H"
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
// (Probably very inefficient) minimum containment sphere calculation.
|
// (Probably very inefficient) minimum containment sphere calculation.
|
||||||
|
|||||||
@ -42,6 +42,7 @@ SourceFiles
|
|||||||
#include "point.H"
|
#include "point.H"
|
||||||
#include "primitiveFieldsFwd.H"
|
#include "primitiveFieldsFwd.H"
|
||||||
#include "pointHit.H"
|
#include "pointHit.H"
|
||||||
|
#include "Random.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -133,16 +134,42 @@ public:
|
|||||||
|
|
||||||
inline vector Sd() const;
|
inline vector Sd() const;
|
||||||
|
|
||||||
|
//- Return centre (centroid)
|
||||||
|
inline Point centre() const;
|
||||||
|
|
||||||
//- Return volume
|
//- Return volume
|
||||||
inline scalar mag() const;
|
inline scalar mag() const;
|
||||||
|
|
||||||
//- Return circum-centre
|
//- Return circum-centre
|
||||||
inline vector circumCentre() const;
|
inline Point circumCentre() const;
|
||||||
|
|
||||||
//- Return circum-radius
|
//- Return circum-radius
|
||||||
inline scalar circumRadius() const;
|
inline scalar circumRadius() const;
|
||||||
|
|
||||||
|
//- Return quality: Ratio of tetrahedron and circum-sphere
|
||||||
|
// volume, scaled so that a regular tetrahedron has a
|
||||||
|
// quality of 1
|
||||||
|
inline scalar quality() const;
|
||||||
|
|
||||||
|
//- Return a random point in the tetrahedron from a
|
||||||
|
// uniform distribution
|
||||||
|
inline Point randomPoint(Random& rndGen) const;
|
||||||
|
|
||||||
|
//- Calculate the barycentric coordinates of the given
|
||||||
|
// point, in the same order as a, b, c, d. Returns the
|
||||||
|
// determinant of the solution.
|
||||||
|
inline scalar barycentric
|
||||||
|
(
|
||||||
|
const point& pt,
|
||||||
|
List<scalar>& bary
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Return nearest point to p on tetrahedron
|
||||||
|
inline pointHit nearestPoint
|
||||||
|
(
|
||||||
|
const point& p
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Return (min)containment sphere, i.e. the smallest sphere with
|
//- Return (min)containment sphere, i.e. the smallest sphere with
|
||||||
// all points inside. Returns pointHit with:
|
// all points inside. Returns pointHit with:
|
||||||
// - hit : if sphere is equal to circumsphere
|
// - hit : if sphere is equal to circumsphere
|
||||||
|
|||||||
@ -125,6 +125,13 @@ inline vector tetrahedron<Point, PointRef>::Sd() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Point, class PointRef>
|
||||||
|
inline Point tetrahedron<Point, PointRef>::centre() const
|
||||||
|
{
|
||||||
|
return 0.25*(a_ + b_ + c_ + d_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class Point, class PointRef>
|
template<class Point, class PointRef>
|
||||||
inline scalar tetrahedron<Point, PointRef>::mag() const
|
inline scalar tetrahedron<Point, PointRef>::mag() const
|
||||||
{
|
{
|
||||||
@ -133,19 +140,19 @@ inline scalar tetrahedron<Point, PointRef>::mag() const
|
|||||||
|
|
||||||
|
|
||||||
template<class Point, class PointRef>
|
template<class Point, class PointRef>
|
||||||
inline vector tetrahedron<Point, PointRef>::circumCentre() const
|
inline Point tetrahedron<Point, PointRef>::circumCentre() const
|
||||||
{
|
{
|
||||||
vector a = b_ - a_;
|
vector a = b_ - a_;
|
||||||
vector b = c_ - a_;
|
vector b = c_ - a_;
|
||||||
vector c = d_ - a_;
|
vector c = d_ - a_;
|
||||||
|
|
||||||
scalar lamda = magSqr(c) - (a&c);
|
scalar lambda = magSqr(c) - (a & c);
|
||||||
scalar mu = magSqr(b) - (a&b);
|
scalar mu = magSqr(b) - (a & b);
|
||||||
|
|
||||||
vector ba = b^a;
|
vector ba = b ^ a;
|
||||||
vector ca = c^a;
|
vector ca = c ^ a;
|
||||||
|
|
||||||
return a_ + 0.5*(a + (lamda*ba - mu*ca)/(c&ba));
|
return a_ + 0.5*(a + (lambda*ba - mu*ca)/((c & ba) + ROOTVSMALL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -156,6 +163,196 @@ inline scalar tetrahedron<Point, PointRef>::circumRadius() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Point, class PointRef>
|
||||||
|
inline scalar tetrahedron<Point, PointRef>::quality() const
|
||||||
|
{
|
||||||
|
// Note: 8/(9*sqrt(3)) = 0.5132002393
|
||||||
|
|
||||||
|
return mag()/(0.5132002393*pow3(min(circumRadius(), GREAT)) + ROOTVSMALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Point, class PointRef>
|
||||||
|
inline Point tetrahedron<Point, PointRef>::randomPoint(Random& rndGen) const
|
||||||
|
{
|
||||||
|
// Adapted from
|
||||||
|
// http://vcg.isti.cnr.it/activities/geometryegraphics/pointintetraedro.html
|
||||||
|
|
||||||
|
scalar s = rndGen.scalar01();
|
||||||
|
scalar t = rndGen.scalar01();
|
||||||
|
scalar u = rndGen.scalar01();
|
||||||
|
|
||||||
|
if (s + t > 1.0)
|
||||||
|
{
|
||||||
|
s = 1.0 - s;
|
||||||
|
t = 1.0 - t;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t + u > 1.0)
|
||||||
|
{
|
||||||
|
scalar tmp = u;
|
||||||
|
u = 1.0 - s - t;
|
||||||
|
t = 1.0 - tmp;
|
||||||
|
}
|
||||||
|
else if (s + t + u > 1.0)
|
||||||
|
{
|
||||||
|
scalar tmp = u;
|
||||||
|
u = s + t + u - 1.0;
|
||||||
|
s = 1.0 - t - tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (1 - s - t - u)*a_ + s*b_ + t*c_ + u*d_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Point, class PointRef>
|
||||||
|
scalar tetrahedron<Point, PointRef>::barycentric
|
||||||
|
(
|
||||||
|
const point& pt,
|
||||||
|
List<scalar>& bary
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// From:
|
||||||
|
// http://en.wikipedia.org/wiki/Barycentric_coordinate_system_(mathematics)
|
||||||
|
|
||||||
|
vector e0(a_ - d_);
|
||||||
|
vector e1(b_ - d_);
|
||||||
|
vector e2(c_ - d_);
|
||||||
|
|
||||||
|
tensor t
|
||||||
|
(
|
||||||
|
e0.x(), e1.x(), e2.x(),
|
||||||
|
e0.y(), e1.y(), e2.y(),
|
||||||
|
e0.z(), e1.z(), e2.z()
|
||||||
|
);
|
||||||
|
|
||||||
|
scalar detT = det(t);
|
||||||
|
|
||||||
|
if (Foam::mag(detT) < SMALL)
|
||||||
|
{
|
||||||
|
WarningIn
|
||||||
|
(
|
||||||
|
"List<scalar> tetrahedron<Point, PointRef>::barycentric"
|
||||||
|
"("
|
||||||
|
"const point& pt"
|
||||||
|
") const"
|
||||||
|
)
|
||||||
|
<< "Degenerate triangle - returning 1/4 barycentric coordinates."
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
bary = List<scalar>(4, 0.25);
|
||||||
|
|
||||||
|
return detT;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector res = inv(t, detT) & (pt - d_);
|
||||||
|
|
||||||
|
bary.setSize(4);
|
||||||
|
|
||||||
|
bary[0] = res.x();
|
||||||
|
bary[1] = res.y();
|
||||||
|
bary[2] = res.z();
|
||||||
|
bary[3] = (1.0 - res.x() - res.y() - res.z());
|
||||||
|
|
||||||
|
return detT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Point, class PointRef>
|
||||||
|
inline pointHit tetrahedron<Point, PointRef>::nearestPoint
|
||||||
|
(
|
||||||
|
const point& p
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Adapted from:
|
||||||
|
// Real-time collision detection, Christer Ericson, 2005, p142-144
|
||||||
|
|
||||||
|
// Assuming initially that the point is inside all of the
|
||||||
|
// halfspaces, so closest to itself.
|
||||||
|
|
||||||
|
point closestPt = p;
|
||||||
|
|
||||||
|
scalar minOutsideDistance = VGREAT;
|
||||||
|
|
||||||
|
bool inside = true;
|
||||||
|
|
||||||
|
if (((p - b_) & Sa()) >= 0)
|
||||||
|
{
|
||||||
|
// p is outside halfspace plane of tri
|
||||||
|
pointHit info = triangle<Point, PointRef>(b_, c_, d_).nearestPoint(p);
|
||||||
|
|
||||||
|
inside = false;
|
||||||
|
|
||||||
|
if (info.distance() < minOutsideDistance)
|
||||||
|
{
|
||||||
|
closestPt = info.rawPoint();
|
||||||
|
|
||||||
|
minOutsideDistance = info.distance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((p - a_) & Sb()) >= 0)
|
||||||
|
{
|
||||||
|
// p is outside halfspace plane of tri
|
||||||
|
pointHit info = triangle<Point, PointRef>(a_, d_, c_).nearestPoint(p);
|
||||||
|
|
||||||
|
inside = false;
|
||||||
|
|
||||||
|
if (info.distance() < minOutsideDistance)
|
||||||
|
{
|
||||||
|
closestPt = info.rawPoint();
|
||||||
|
|
||||||
|
minOutsideDistance = info.distance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((p - a_) & Sc()) >= 0)
|
||||||
|
{
|
||||||
|
// p is outside halfspace plane of tri
|
||||||
|
pointHit info = triangle<Point, PointRef>(a_, b_, d_).nearestPoint(p);
|
||||||
|
|
||||||
|
inside = false;
|
||||||
|
|
||||||
|
if (info.distance() < minOutsideDistance)
|
||||||
|
{
|
||||||
|
closestPt = info.rawPoint();
|
||||||
|
|
||||||
|
minOutsideDistance = info.distance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((p - a_) & Sd()) >= 0)
|
||||||
|
{
|
||||||
|
// p is outside halfspace plane of tri
|
||||||
|
pointHit info = triangle<Point, PointRef>(a_, c_, b_).nearestPoint(p);
|
||||||
|
|
||||||
|
inside = false;
|
||||||
|
|
||||||
|
if (info.distance() < minOutsideDistance)
|
||||||
|
{
|
||||||
|
closestPt = info.rawPoint();
|
||||||
|
|
||||||
|
minOutsideDistance = info.distance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the point is inside, then the distance to the closest point
|
||||||
|
// is zero
|
||||||
|
if (inside)
|
||||||
|
{
|
||||||
|
minOutsideDistance = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pointHit
|
||||||
|
(
|
||||||
|
inside,
|
||||||
|
closestPt,
|
||||||
|
minOutsideDistance,
|
||||||
|
!inside
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class point, class pointRef>
|
template<class point, class pointRef>
|
||||||
|
|||||||
@ -39,7 +39,7 @@ SourceFiles
|
|||||||
#include "vector.H"
|
#include "vector.H"
|
||||||
#include "tensor.H"
|
#include "tensor.H"
|
||||||
#include "pointHit.H"
|
#include "pointHit.H"
|
||||||
|
#include "Random.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -141,12 +141,14 @@ public:
|
|||||||
inline vector normal() const;
|
inline vector normal() const;
|
||||||
|
|
||||||
//- Return circum-centre
|
//- Return circum-centre
|
||||||
inline vector circumCentre() const;
|
inline Point circumCentre() const;
|
||||||
|
|
||||||
//- Return circum-radius
|
//- Return circum-radius
|
||||||
inline scalar circumRadius() const;
|
inline scalar circumRadius() const;
|
||||||
|
|
||||||
//- Return quality: Ratio triangle and circum-circle area
|
//- Return quality: Ratio of triangle and circum-circle
|
||||||
|
// area, scaled so that an equilateral triangle has a
|
||||||
|
// quality of 1
|
||||||
inline scalar quality() const;
|
inline scalar quality() const;
|
||||||
|
|
||||||
//- Return swept-volume
|
//- Return swept-volume
|
||||||
@ -160,6 +162,19 @@ public:
|
|||||||
scalar density = 1.0
|
scalar density = 1.0
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
|
//- Return a random point on the triangle from a uniform
|
||||||
|
// distribution
|
||||||
|
inline Point randomPoint(Random& rndGen) const;
|
||||||
|
|
||||||
|
//- Calculate the barycentric coordinates of the given
|
||||||
|
// point, in the same order as a, b, c. Returns the
|
||||||
|
// determinant of the solution.
|
||||||
|
inline scalar barycentric
|
||||||
|
(
|
||||||
|
const point& pt,
|
||||||
|
List<scalar>& bary
|
||||||
|
) const;
|
||||||
|
|
||||||
//- Return point intersection with a ray.
|
//- Return point intersection with a ray.
|
||||||
// For a hit, the distance is signed. Positive number
|
// For a hit, the distance is signed. Positive number
|
||||||
// represents the point in front of triangle.
|
// represents the point in front of triangle.
|
||||||
|
|||||||
@ -259,7 +259,7 @@ inline vector triangle<Point, PointRef>::normal() const
|
|||||||
|
|
||||||
|
|
||||||
template<class Point, class PointRef>
|
template<class Point, class PointRef>
|
||||||
inline vector triangle<Point, PointRef>::circumCentre() const
|
inline Point triangle<Point, PointRef>::circumCentre() const
|
||||||
{
|
{
|
||||||
scalar d1 = (c_ - a_)&(b_ - a_);
|
scalar d1 = (c_ - a_)&(b_ - a_);
|
||||||
scalar d2 = -(c_ - b_)&(b_ - a_);
|
scalar d2 = -(c_ - b_)&(b_ - a_);
|
||||||
@ -303,12 +303,14 @@ inline scalar triangle<Point, PointRef>::circumRadius() const
|
|||||||
template<class Point, class PointRef>
|
template<class Point, class PointRef>
|
||||||
inline scalar triangle<Point, PointRef>::quality() const
|
inline scalar triangle<Point, PointRef>::quality() const
|
||||||
{
|
{
|
||||||
|
// Note: 3*sqr(3)/(4*pi) = 0.4134966716
|
||||||
|
|
||||||
return
|
return
|
||||||
mag()
|
mag()
|
||||||
/ (
|
/ (
|
||||||
constant::mathematical::pi
|
constant::mathematical::pi
|
||||||
*Foam::sqr(circumRadius())
|
*Foam::sqr(circumRadius())
|
||||||
*0.413497
|
*0.4134966716
|
||||||
+ VSMALL
|
+ VSMALL
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -366,6 +368,72 @@ inline tensor triangle<Point, PointRef>::inertia
|
|||||||
*density;
|
*density;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Point, class PointRef>
|
||||||
|
inline Point triangle<Point, PointRef>::randomPoint(Random& rndGen) const
|
||||||
|
{
|
||||||
|
// Generating Random Points in Triangles
|
||||||
|
// by Greg Turk
|
||||||
|
// from "Graphics Gems", Academic Press, 1990
|
||||||
|
// http://tog.acm.org/GraphicsGems/gems/TriPoints.c
|
||||||
|
|
||||||
|
scalar s = rndGen.scalar01();
|
||||||
|
|
||||||
|
scalar t = sqrt(rndGen.scalar01());
|
||||||
|
|
||||||
|
return (1 - t)*a_ + (1 - s)*t*b_ + s*t*c_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Point, class PointRef>
|
||||||
|
scalar triangle<Point, PointRef>::barycentric
|
||||||
|
(
|
||||||
|
const point& pt,
|
||||||
|
List<scalar>& bary
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// From:
|
||||||
|
// Real-time collision detection, Christer Ericson, 2005, p47-48
|
||||||
|
|
||||||
|
vector v0 = b_ - a_;
|
||||||
|
vector v1 = c_ - a_;
|
||||||
|
vector v2 = pt - a_;
|
||||||
|
|
||||||
|
scalar d00 = v0 & v0;
|
||||||
|
scalar d01 = v0 & v1;
|
||||||
|
scalar d11 = v1 & v1;
|
||||||
|
scalar d20 = v2 & v0;
|
||||||
|
scalar d21 = v2 & v1;
|
||||||
|
|
||||||
|
scalar denom = d00*d11 - d01*d01;
|
||||||
|
|
||||||
|
if (Foam::mag(denom) < SMALL)
|
||||||
|
{
|
||||||
|
WarningIn
|
||||||
|
(
|
||||||
|
"List<scalar> triangle<Point, PointRef>::barycentric"
|
||||||
|
"("
|
||||||
|
"const point& pt"
|
||||||
|
") const"
|
||||||
|
)
|
||||||
|
<< "Degenerate triangle - returning 1/3 barycentric coordinates."
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
bary = List<scalar>(3, 1.0/3.0);
|
||||||
|
|
||||||
|
return denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
bary.setSize(3);
|
||||||
|
|
||||||
|
bary[0] = (d11*d20 - d01*d21)/denom;
|
||||||
|
bary[1] = (d00*d21 - d01*d20)/denom;
|
||||||
|
bary[2] = 1.0 - bary[0] - bary[1];
|
||||||
|
|
||||||
|
return denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class Point, class PointRef>
|
template<class Point, class PointRef>
|
||||||
inline pointHit triangle<Point, PointRef>::ray
|
inline pointHit triangle<Point, PointRef>::ray
|
||||||
(
|
(
|
||||||
@ -775,4 +843,3 @@ inline Ostream& operator<<(Ostream& os, const triangle<Point, PointRef>& t)
|
|||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|
||||||
|
|||||||
@ -481,7 +481,7 @@ inline Tensor<Cmpt> cof(const Tensor<Cmpt>& t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//- Return the inverse of a tensor give the determinant
|
//- Return the inverse of a tensor given the determinant
|
||||||
template <class Cmpt>
|
template <class Cmpt>
|
||||||
inline Tensor<Cmpt> inv(const Tensor<Cmpt>& t, const Cmpt dett)
|
inline Tensor<Cmpt> inv(const Tensor<Cmpt>& t, const Cmpt dett)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -68,9 +68,9 @@ bool Foam::motionSmoother::checkMesh
|
|||||||
(
|
(
|
||||||
readScalar(dict.lookup("minVol", true))
|
readScalar(dict.lookup("minVol", true))
|
||||||
);
|
);
|
||||||
const scalar minTetVol
|
const scalar minTetQuality
|
||||||
(
|
(
|
||||||
readScalar(dict.lookup("minTetVol", true))
|
readScalar(dict.lookup("minTetQuality", true))
|
||||||
);
|
);
|
||||||
const scalar maxConcave
|
const scalar maxConcave
|
||||||
(
|
(
|
||||||
@ -160,12 +160,12 @@ bool Foam::motionSmoother::checkMesh
|
|||||||
nWrongFaces = nNewWrongFaces;
|
nWrongFaces = nNewWrongFaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minTetVol > -GREAT)
|
if (minTetQuality > -GREAT)
|
||||||
{
|
{
|
||||||
polyMeshGeometry::checkFaceTets
|
polyMeshGeometry::checkFaceTets
|
||||||
(
|
(
|
||||||
report,
|
report,
|
||||||
minTetVol,
|
minTetQuality,
|
||||||
mesh,
|
mesh,
|
||||||
mesh.cellCentres(),
|
mesh.cellCentres(),
|
||||||
mesh.faceCentres(),
|
mesh.faceCentres(),
|
||||||
@ -177,8 +177,8 @@ bool Foam::motionSmoother::checkMesh
|
|||||||
|
|
||||||
label nNewWrongFaces = returnReduce(wrongFaces.size(), sumOp<label>());
|
label nNewWrongFaces = returnReduce(wrongFaces.size(), sumOp<label>());
|
||||||
|
|
||||||
Info<< " faces with face-decomposition tet volume < "
|
Info<< " faces with face-decomposition tet quality < "
|
||||||
<< setw(5) << minTetVol << " : "
|
<< setw(5) << minTetQuality << " : "
|
||||||
<< nNewWrongFaces-nWrongFaces << endl;
|
<< nNewWrongFaces-nWrongFaces << endl;
|
||||||
|
|
||||||
nWrongFaces = nNewWrongFaces;
|
nWrongFaces = nNewWrongFaces;
|
||||||
@ -443,9 +443,9 @@ bool Foam::motionSmoother::checkMesh
|
|||||||
(
|
(
|
||||||
readScalar(dict.lookup("minVol", true))
|
readScalar(dict.lookup("minVol", true))
|
||||||
);
|
);
|
||||||
const scalar minTetVol
|
const scalar minTetQuality
|
||||||
(
|
(
|
||||||
readScalar(dict.lookup("minTetVol", true))
|
readScalar(dict.lookup("minTetQuality", true))
|
||||||
);
|
);
|
||||||
const scalar maxConcave
|
const scalar maxConcave
|
||||||
(
|
(
|
||||||
@ -531,12 +531,12 @@ bool Foam::motionSmoother::checkMesh
|
|||||||
nWrongFaces = nNewWrongFaces;
|
nWrongFaces = nNewWrongFaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (minTetVol > -GREAT)
|
if (minTetQuality > -GREAT)
|
||||||
{
|
{
|
||||||
meshGeom.checkFaceTets
|
meshGeom.checkFaceTets
|
||||||
(
|
(
|
||||||
report,
|
report,
|
||||||
minTetVol,
|
minTetQuality,
|
||||||
meshGeom.mesh().points(),
|
meshGeom.mesh().points(),
|
||||||
checkFaces,
|
checkFaces,
|
||||||
baffles,
|
baffles,
|
||||||
@ -545,8 +545,8 @@ bool Foam::motionSmoother::checkMesh
|
|||||||
|
|
||||||
label nNewWrongFaces = returnReduce(wrongFaces.size(), sumOp<label>());
|
label nNewWrongFaces = returnReduce(wrongFaces.size(), sumOp<label>());
|
||||||
|
|
||||||
Info<< " faces with face-decomposition tet volume < "
|
Info<< " faces with face-decomposition tet quality < "
|
||||||
<< setw(5) << minTetVol << " : "
|
<< setw(5) << minTetQuality << " : "
|
||||||
<< nNewWrongFaces-nWrongFaces << endl;
|
<< nNewWrongFaces-nWrongFaces << endl;
|
||||||
|
|
||||||
nWrongFaces = nNewWrongFaces;
|
nWrongFaces = nNewWrongFaces;
|
||||||
|
|||||||
@ -24,6 +24,7 @@ License
|
|||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "polyMeshGeometry.H"
|
#include "polyMeshGeometry.H"
|
||||||
|
#include "polyMeshTetDecomposition.H"
|
||||||
#include "pyramidPointFaceRef.H"
|
#include "pyramidPointFaceRef.H"
|
||||||
#include "tetPointRef.H"
|
#include "tetPointRef.H"
|
||||||
#include "syncTools.H"
|
#include "syncTools.H"
|
||||||
@ -313,7 +314,7 @@ bool Foam::polyMeshGeometry::checkFaceTet
|
|||||||
(
|
(
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const bool report,
|
const bool report,
|
||||||
const scalar minTetVol,
|
const scalar minTetQuality,
|
||||||
const pointField& p,
|
const pointField& p,
|
||||||
const label faceI,
|
const label faceI,
|
||||||
const point& fc, // face centre
|
const point& fc, // face centre
|
||||||
@ -326,15 +327,15 @@ bool Foam::polyMeshGeometry::checkFaceTet
|
|||||||
|
|
||||||
forAll(f, fp)
|
forAll(f, fp)
|
||||||
{
|
{
|
||||||
scalar tetVol = tetPointRef
|
scalar tetQual = tetPointRef
|
||||||
(
|
(
|
||||||
p[f[fp]],
|
p[f[fp]],
|
||||||
p[f.nextLabel(fp)],
|
p[f.nextLabel(fp)],
|
||||||
fc,
|
fc,
|
||||||
cc
|
cc
|
||||||
).mag();
|
).quality();
|
||||||
|
|
||||||
if (tetVol < minTetVol)
|
if (tetQual < minTetQuality)
|
||||||
{
|
{
|
||||||
if (report)
|
if (report)
|
||||||
{
|
{
|
||||||
@ -345,7 +346,7 @@ bool Foam::polyMeshGeometry::checkFaceTet
|
|||||||
<< "face " << faceI
|
<< "face " << faceI
|
||||||
<< " has a triangle that points the wrong way."
|
<< " has a triangle that points the wrong way."
|
||||||
<< endl
|
<< endl
|
||||||
<< "Tet volume: " << tetVol
|
<< "Tet quality: " << tetQual
|
||||||
<< " Face " << faceI
|
<< " Face " << faceI
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
@ -423,16 +424,15 @@ bool Foam::polyMeshGeometry::checkFaceDotProduct
|
|||||||
// Severe nonorthogonality threshold
|
// Severe nonorthogonality threshold
|
||||||
const scalar severeNonorthogonalityThreshold = ::cos(degToRad(orthWarn));
|
const scalar severeNonorthogonalityThreshold = ::cos(degToRad(orthWarn));
|
||||||
|
|
||||||
|
|
||||||
// Calculate coupled cell centre
|
// Calculate coupled cell centre
|
||||||
pointField neiCc(mesh.nFaces()-mesh.nInternalFaces());
|
pointField neiCc(mesh.nFaces() - mesh.nInternalFaces());
|
||||||
|
|
||||||
for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++)
|
for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++)
|
||||||
{
|
{
|
||||||
neiCc[faceI-mesh.nInternalFaces()] = cellCentres[own[faceI]];
|
neiCc[faceI-mesh.nInternalFaces()] = cellCentres[own[faceI]];
|
||||||
}
|
}
|
||||||
syncTools::swapBoundaryFacePositions(mesh, neiCc);
|
|
||||||
|
|
||||||
|
syncTools::swapBoundaryFacePositions(mesh, neiCc);
|
||||||
|
|
||||||
scalar minDDotS = GREAT;
|
scalar minDDotS = GREAT;
|
||||||
|
|
||||||
@ -754,7 +754,7 @@ bool Foam::polyMeshGeometry::checkFacePyramids
|
|||||||
"polyMeshGeometry::checkFacePyramids("
|
"polyMeshGeometry::checkFacePyramids("
|
||||||
"const bool, const scalar, const pointField&"
|
"const bool, const scalar, const pointField&"
|
||||||
", const labelList&, labelHashSet*)"
|
", const labelList&, labelHashSet*)"
|
||||||
) << "Error in face pyramids: faces pointing the wrong way!"
|
) << "Error in face pyramids: faces pointing the wrong way."
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -775,7 +775,7 @@ bool Foam::polyMeshGeometry::checkFacePyramids
|
|||||||
bool Foam::polyMeshGeometry::checkFaceTets
|
bool Foam::polyMeshGeometry::checkFaceTets
|
||||||
(
|
(
|
||||||
const bool report,
|
const bool report,
|
||||||
const scalar minTetVol,
|
const scalar minTetQuality,
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const vectorField& cellCentres,
|
const vectorField& cellCentres,
|
||||||
const vectorField& faceCentres,
|
const vectorField& faceCentres,
|
||||||
@ -785,11 +785,23 @@ bool Foam::polyMeshGeometry::checkFaceTets
|
|||||||
labelHashSet* setPtr
|
labelHashSet* setPtr
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// check whether face area vector points to the cell with higher label
|
// check whether decomposing each cell into tets results in
|
||||||
|
// positive volume, non-flat tets
|
||||||
const labelList& own = mesh.faceOwner();
|
const labelList& own = mesh.faceOwner();
|
||||||
const labelList& nei = mesh.faceNeighbour();
|
const labelList& nei = mesh.faceNeighbour();
|
||||||
|
const polyBoundaryMesh& patches = mesh.boundaryMesh();
|
||||||
|
|
||||||
label nErrorPyrs = 0;
|
// Calculate coupled cell centre
|
||||||
|
pointField neiCc(mesh.nFaces() - mesh.nInternalFaces());
|
||||||
|
|
||||||
|
for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++)
|
||||||
|
{
|
||||||
|
neiCc[faceI - mesh.nInternalFaces()] = cellCentres[own[faceI]];
|
||||||
|
}
|
||||||
|
|
||||||
|
syncTools::swapBoundaryFacePositions(mesh, neiCc);
|
||||||
|
|
||||||
|
label nErrorTets = 0;
|
||||||
|
|
||||||
forAll(checkFaces, i)
|
forAll(checkFaces, i)
|
||||||
{
|
{
|
||||||
@ -801,7 +813,7 @@ bool Foam::polyMeshGeometry::checkFaceTets
|
|||||||
(
|
(
|
||||||
mesh,
|
mesh,
|
||||||
report,
|
report,
|
||||||
minTetVol,
|
minTetQuality,
|
||||||
p,
|
p,
|
||||||
faceI,
|
faceI,
|
||||||
cellCentres[own[faceI]], // face centre
|
cellCentres[own[faceI]], // face centre
|
||||||
@ -811,26 +823,94 @@ bool Foam::polyMeshGeometry::checkFaceTets
|
|||||||
|
|
||||||
if (tetError)
|
if (tetError)
|
||||||
{
|
{
|
||||||
nErrorPyrs++;
|
nErrorTets++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mesh.isInternalFace(faceI))
|
if (mesh.isInternalFace(faceI))
|
||||||
{
|
{
|
||||||
// Create the neighbour pyramid - it will have positive volume
|
// Create the neighbour tets - they will have positive volume
|
||||||
bool tetError = checkFaceTet
|
bool tetError = checkFaceTet
|
||||||
(
|
(
|
||||||
mesh,
|
mesh,
|
||||||
report,
|
report,
|
||||||
minTetVol,
|
minTetQuality,
|
||||||
p,
|
p,
|
||||||
faceI,
|
faceI,
|
||||||
faceCentres[faceI], // face centre
|
faceCentres[faceI], // face centre
|
||||||
cellCentres[nei[faceI]], // cell centre
|
cellCentres[nei[faceI]], // cell centre
|
||||||
setPtr
|
setPtr
|
||||||
);
|
);
|
||||||
|
|
||||||
if (tetError)
|
if (tetError)
|
||||||
{
|
{
|
||||||
nErrorPyrs++;
|
nErrorTets++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
polyMeshTetDecomposition::findSharedBasePoint
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
faceI,
|
||||||
|
minTetQuality,
|
||||||
|
report
|
||||||
|
) == -1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (setPtr)
|
||||||
|
{
|
||||||
|
setPtr->insert(faceI);
|
||||||
|
}
|
||||||
|
|
||||||
|
nErrorTets++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label patchI = patches.whichPatch(faceI);
|
||||||
|
|
||||||
|
if (patches[patchI].coupled())
|
||||||
|
{
|
||||||
|
if
|
||||||
|
(
|
||||||
|
polyMeshTetDecomposition::findSharedBasePoint
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
faceI,
|
||||||
|
neiCc[faceI - mesh.nInternalFaces()],
|
||||||
|
minTetQuality,
|
||||||
|
report
|
||||||
|
) == -1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (setPtr)
|
||||||
|
{
|
||||||
|
setPtr->insert(faceI);
|
||||||
|
}
|
||||||
|
|
||||||
|
nErrorTets++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if
|
||||||
|
(
|
||||||
|
polyMeshTetDecomposition::findBasePoint
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
faceI,
|
||||||
|
minTetQuality,
|
||||||
|
report
|
||||||
|
) == -1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (setPtr)
|
||||||
|
{
|
||||||
|
setPtr->insert(faceI);
|
||||||
|
}
|
||||||
|
|
||||||
|
nErrorTets++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -844,7 +924,7 @@ bool Foam::polyMeshGeometry::checkFaceTets
|
|||||||
(
|
(
|
||||||
mesh,
|
mesh,
|
||||||
report,
|
report,
|
||||||
minTetVol,
|
minTetQuality,
|
||||||
p,
|
p,
|
||||||
face0,
|
face0,
|
||||||
cellCentres[own[face0]], // face centre
|
cellCentres[own[face0]], // face centre
|
||||||
@ -854,15 +934,15 @@ bool Foam::polyMeshGeometry::checkFaceTets
|
|||||||
|
|
||||||
if (tetError)
|
if (tetError)
|
||||||
{
|
{
|
||||||
nErrorPyrs++;
|
nErrorTets++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the neighbour pyramid - it will have positive volume
|
// Create the neighbour tets - they will have positive volume
|
||||||
tetError = checkFaceTet
|
tetError = checkFaceTet
|
||||||
(
|
(
|
||||||
mesh,
|
mesh,
|
||||||
report,
|
report,
|
||||||
minTetVol,
|
minTetQuality,
|
||||||
p,
|
p,
|
||||||
face0,
|
face0,
|
||||||
faceCentres[face0], // face centre
|
faceCentres[face0], // face centre
|
||||||
@ -872,13 +952,33 @@ bool Foam::polyMeshGeometry::checkFaceTets
|
|||||||
|
|
||||||
if (tetError)
|
if (tetError)
|
||||||
{
|
{
|
||||||
nErrorPyrs++;
|
nErrorTets++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
polyMeshTetDecomposition::findSharedBasePoint
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
face0,
|
||||||
|
cellCentres[own[face1]],
|
||||||
|
minTetQuality,
|
||||||
|
report
|
||||||
|
) == -1
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (setPtr)
|
||||||
|
{
|
||||||
|
setPtr->insert(face0);
|
||||||
|
}
|
||||||
|
|
||||||
|
nErrorTets++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reduce(nErrorPyrs, sumOp<label>());
|
reduce(nErrorTets, sumOp<label>());
|
||||||
|
|
||||||
if (nErrorPyrs > 0)
|
if (nErrorTets > 0)
|
||||||
{
|
{
|
||||||
if (report)
|
if (report)
|
||||||
{
|
{
|
||||||
@ -887,7 +987,7 @@ bool Foam::polyMeshGeometry::checkFaceTets
|
|||||||
"polyMeshGeometry::checkFaceTets("
|
"polyMeshGeometry::checkFaceTets("
|
||||||
"const bool, const scalar, const pointField&, const pointField&"
|
"const bool, const scalar, const pointField&, const pointField&"
|
||||||
", const labelList&, labelHashSet*)"
|
", const labelList&, labelHashSet*)"
|
||||||
) << "Error in face pyramids: faces pointing the wrong way!"
|
) << "Error in face decomposition: negative tets."
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2135,7 +2235,7 @@ bool Foam::polyMeshGeometry::checkFacePyramids
|
|||||||
bool Foam::polyMeshGeometry::checkFaceTets
|
bool Foam::polyMeshGeometry::checkFaceTets
|
||||||
(
|
(
|
||||||
const bool report,
|
const bool report,
|
||||||
const scalar minTetVol,
|
const scalar minTetQuality,
|
||||||
const pointField& p,
|
const pointField& p,
|
||||||
const labelList& checkFaces,
|
const labelList& checkFaces,
|
||||||
const List<labelPair>& baffles,
|
const List<labelPair>& baffles,
|
||||||
@ -2145,7 +2245,7 @@ bool Foam::polyMeshGeometry::checkFaceTets
|
|||||||
return checkFaceTets
|
return checkFaceTets
|
||||||
(
|
(
|
||||||
report,
|
report,
|
||||||
minTetVol,
|
minTetQuality,
|
||||||
mesh_,
|
mesh_,
|
||||||
cellCentres_,
|
cellCentres_,
|
||||||
faceCentres_,
|
faceCentres_,
|
||||||
|
|||||||
@ -113,7 +113,7 @@ class polyMeshGeometry
|
|||||||
(
|
(
|
||||||
const polyMesh&,
|
const polyMesh&,
|
||||||
const bool report,
|
const bool report,
|
||||||
const scalar minTetVol,
|
const scalar minTetQuality,
|
||||||
const pointField& p,
|
const pointField& p,
|
||||||
const label faceI,
|
const label faceI,
|
||||||
const point& fc, // face centre
|
const point& fc, // face centre
|
||||||
@ -121,6 +121,7 @@ class polyMeshGeometry
|
|||||||
labelHashSet* setPtr
|
labelHashSet* setPtr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ClassName("polyMeshGeometry");
|
ClassName("polyMeshGeometry");
|
||||||
@ -350,7 +351,7 @@ public:
|
|||||||
bool checkFaceTets
|
bool checkFaceTets
|
||||||
(
|
(
|
||||||
const bool report,
|
const bool report,
|
||||||
const scalar minTetVol,
|
const scalar minTetQuality,
|
||||||
const pointField& p,
|
const pointField& p,
|
||||||
const labelList& checkFaces,
|
const labelList& checkFaces,
|
||||||
const List<labelPair>& baffles,
|
const List<labelPair>& baffles,
|
||||||
|
|||||||
@ -38,6 +38,7 @@ Description
|
|||||||
#include "typeInfo.H"
|
#include "typeInfo.H"
|
||||||
#include "autoPtr.H"
|
#include "autoPtr.H"
|
||||||
#include "runTimeSelectionTables.H"
|
#include "runTimeSelectionTables.H"
|
||||||
|
#include "tetIndices.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -130,9 +131,23 @@ public:
|
|||||||
virtual Type interpolate
|
virtual Type interpolate
|
||||||
(
|
(
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label nCell,
|
const label cellI,
|
||||||
const label facei = -1
|
const label faceI = -1
|
||||||
) const = 0;
|
) const = 0;
|
||||||
|
|
||||||
|
//- Interpolate field to the given point in the tetrahedron
|
||||||
|
// defined by the given indices. Calls interpolate function
|
||||||
|
// above here execpt where overridden by derived
|
||||||
|
// interpolation types.
|
||||||
|
virtual Type interpolate
|
||||||
|
(
|
||||||
|
const vector& position,
|
||||||
|
const tetIndices& tetIs,
|
||||||
|
const label faceI = -1
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return interpolate(position, tetIs.cell(), faceI);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -49,11 +49,11 @@ template<class Type>
|
|||||||
Type interpolationCell<Type>::interpolate
|
Type interpolationCell<Type>::interpolate
|
||||||
(
|
(
|
||||||
const vector&,
|
const vector&,
|
||||||
const label celli,
|
const label cellI,
|
||||||
const label
|
const label
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
return this->psi_[celli];
|
return this->psi_[cellI];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -72,8 +72,8 @@ public:
|
|||||||
Type interpolate
|
Type interpolate
|
||||||
(
|
(
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label nCell,
|
const label cellI,
|
||||||
const label facei = -1
|
const label faceI = -1
|
||||||
) const;
|
) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -25,10 +25,13 @@ License
|
|||||||
|
|
||||||
#include "cellPointWeight.H"
|
#include "cellPointWeight.H"
|
||||||
#include "polyMesh.H"
|
#include "polyMesh.H"
|
||||||
|
#include "tetPointRef.H"
|
||||||
|
#include "polyMeshTetDecomposition.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
int Foam::cellPointWeight::debug(debug::debugSwitch("cellPointWeight", 0));
|
int Foam::cellPointWeight::debug(debug::debugSwitch("cellPointWeight", 0));
|
||||||
|
|
||||||
Foam::scalar Foam::cellPointWeight::tol(SMALL);
|
Foam::scalar Foam::cellPointWeight::tol(SMALL);
|
||||||
|
|
||||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||||
@ -37,148 +40,101 @@ void Foam::cellPointWeight::findTetrahedron
|
|||||||
(
|
(
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label cellIndex
|
const label cellI
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Pout<< "\nFoam::cellPointWeight::findTetrahedron" << nl
|
Pout<< nl << "Foam::cellPointWeight::findTetrahedron" << nl
|
||||||
<< "position = " << position << nl
|
<< "position = " << position << nl
|
||||||
<< "cellIndex = " << cellIndex << endl;
|
<< "cellI = " << cellI << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise closest triangle variables
|
List<tetIndices> cellTets = polyMeshTetDecomposition::cellTetIndices
|
||||||
scalar minUVWClose = VGREAT;
|
|
||||||
label pointIClose = 0;
|
|
||||||
label faceClose = 0;
|
|
||||||
|
|
||||||
const vector& P0 = mesh.cellCentres()[cellIndex];
|
|
||||||
const labelList& cellFaces = mesh.cells()[cellIndex];
|
|
||||||
const scalar cellVolume = mesh.cellVolumes()[cellIndex];
|
|
||||||
|
|
||||||
// Find the tet that the point occupies
|
|
||||||
forAll(cellFaces, faceI)
|
|
||||||
{
|
|
||||||
// Decompose each face into triangles, making a tet when
|
|
||||||
// augmented by the cell centre
|
|
||||||
const labelList& facePoints = mesh.faces()[cellFaces[faceI]];
|
|
||||||
|
|
||||||
label pointI = 1;
|
|
||||||
while ((pointI + 1) < facePoints.size())
|
|
||||||
{
|
|
||||||
// Cartesian co-ordinates of the triangle vertices
|
|
||||||
const vector& P1 = mesh.points()[facePoints[0]];
|
|
||||||
const vector& P2 = mesh.points()[facePoints[pointI]];
|
|
||||||
const vector& P3 = mesh.points()[facePoints[pointI + 1]];
|
|
||||||
|
|
||||||
// Edge vectors
|
|
||||||
const vector e1 = P1 - P0;
|
|
||||||
const vector e2 = P2 - P0;
|
|
||||||
const vector e3 = P3 - P0;
|
|
||||||
|
|
||||||
// Solve for interpolation weighting factors
|
|
||||||
|
|
||||||
// Source term
|
|
||||||
const vector rhs = position - P0;
|
|
||||||
|
|
||||||
// Determinant of coefficients matrix
|
|
||||||
// Note: if det(A) = 0 the tet is degenerate
|
|
||||||
const scalar detA =
|
|
||||||
e1.x()*e2.y()*e3.z() + e2.x()*e3.y()*e1.z()
|
|
||||||
+ e3.x()*e1.y()*e2.z() - e1.x()*e3.y()*e2.z()
|
|
||||||
- e2.x()*e1.y()*e3.z() - e3.x()*e2.y()*e1.z();
|
|
||||||
|
|
||||||
if (mag(detA/cellVolume) > tol)
|
|
||||||
{
|
|
||||||
// Solve using Cramers' rule
|
|
||||||
const scalar u =
|
|
||||||
(
|
(
|
||||||
rhs.x()*e2.y()*e3.z() + e2.x()*e3.y()*rhs.z()
|
mesh,
|
||||||
+ e3.x()*rhs.y()*e2.z() - rhs.x()*e3.y()*e2.z()
|
cellI
|
||||||
- e2.x()*rhs.y()*e3.z() - e3.x()*e2.y()*rhs.z()
|
);
|
||||||
)/detA;
|
|
||||||
|
|
||||||
const scalar v =
|
const faceList& pFaces = mesh.faces();
|
||||||
(
|
const scalar cellVolume = mesh.cellVolumes()[cellI];
|
||||||
e1.x()*rhs.y()*e3.z() + rhs.x()*e3.y()*e1.z()
|
|
||||||
+ e3.x()*e1.y()*rhs.z() - e1.x()*e3.y()*rhs.z()
|
|
||||||
- rhs.x()*e1.y()*e3.z() - e3.x()*rhs.y()*e1.z()
|
|
||||||
)/detA;
|
|
||||||
|
|
||||||
const scalar w =
|
forAll(cellTets, tetI)
|
||||||
(
|
{
|
||||||
e1.x()*e2.y()*rhs.z() + e2.x()*rhs.y()*e1.z()
|
const tetIndices& tetIs = cellTets[tetI];
|
||||||
+ rhs.x()*e1.y()*e2.z() - e1.x()*rhs.y()*e2.z()
|
|
||||||
- e2.x()*e1.y()*rhs.z() - rhs.x()*e2.y()*e1.z()
|
const face& f = pFaces[tetIs.face()];
|
||||||
)/detA;
|
|
||||||
|
// Barycentric coordinates of the position
|
||||||
|
scalar det = tetIs.tet(mesh).barycentric(position, weights_);
|
||||||
|
|
||||||
|
if (mag(det/cellVolume) > tol)
|
||||||
|
{
|
||||||
|
const scalar& u = weights_[0];
|
||||||
|
const scalar& v = weights_[1];
|
||||||
|
const scalar& w = weights_[2];
|
||||||
|
|
||||||
// Check if point is in tet
|
|
||||||
// value = 0 indicates position lies on a tet face
|
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
(u + tol > 0) && (v + tol > 0) && (w + tol > 0)
|
(u + tol > 0)
|
||||||
|
&& (v + tol > 0)
|
||||||
|
&& (w + tol > 0)
|
||||||
&& (u + v + w < 1 + tol)
|
&& (u + v + w < 1 + tol)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
faceVertices_[0] = facePoints[0];
|
faceVertices_[0] = f[tetIs.faceBasePt()];
|
||||||
faceVertices_[1] = facePoints[pointI];
|
faceVertices_[1] = f[tetIs.facePtA()];;
|
||||||
faceVertices_[2] = facePoints[pointI + 1];
|
faceVertices_[2] = f[tetIs.facePtB()];;
|
||||||
|
|
||||||
weights_[0] = u;
|
|
||||||
weights_[1] = v;
|
|
||||||
weights_[2] = w;
|
|
||||||
weights_[3] = 1.0 - (u + v + w);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
scalar minU = mag(u);
|
|
||||||
scalar minV = mag(v);
|
|
||||||
scalar minW = mag(w);
|
|
||||||
if (minU > 1.0)
|
|
||||||
{
|
|
||||||
minU -= 1.0;
|
|
||||||
}
|
|
||||||
if (minV > 1.0)
|
|
||||||
{
|
|
||||||
minV -= 1.0;
|
|
||||||
}
|
|
||||||
if (minW > 1.0)
|
|
||||||
{
|
|
||||||
minW -= 1.0;
|
|
||||||
}
|
|
||||||
const scalar minUVW = mag(minU + minV + minW);
|
|
||||||
|
|
||||||
if (minUVW < minUVWClose)
|
|
||||||
{
|
|
||||||
minUVWClose = minUVW;
|
|
||||||
pointIClose = pointI;
|
|
||||||
faceClose = faceI;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pointI++;
|
// A suitable point in a tetrahedron was not found, find the
|
||||||
|
// nearest.
|
||||||
|
|
||||||
|
scalar minNearDist = VGREAT;
|
||||||
|
|
||||||
|
label nearestTetI = -1;
|
||||||
|
|
||||||
|
forAll(cellTets, tetI)
|
||||||
|
{
|
||||||
|
const tetIndices& tetIs = cellTets[tetI];
|
||||||
|
|
||||||
|
scalar nearDist = tetIs.tet(mesh).nearestPoint(position).distance();
|
||||||
|
|
||||||
|
if (nearDist < minNearDist)
|
||||||
|
{
|
||||||
|
minNearDist = nearDist;
|
||||||
|
|
||||||
|
nearestTetI = tetI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Pout<< "cellPointWeight::findTetrahedron" << nl
|
Pout<< "cellPointWeight::findTetrahedron" << nl
|
||||||
<< " Tetrahedron search failed; using closest tet values to "
|
<< " Tetrahedron search failed; using closest tet to point "
|
||||||
<< "point " << nl << " cell: " << cellIndex << nl << endl;
|
<< position << nl
|
||||||
|
<< " cell: "
|
||||||
|
<< cellI << nl
|
||||||
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
const labelList& facePointsClose = mesh.faces()[cellFaces[faceClose]];
|
|
||||||
faceVertices_[0] = facePointsClose[0];
|
|
||||||
faceVertices_[1] = facePointsClose[pointIClose];
|
|
||||||
faceVertices_[2] = facePointsClose[pointIClose + 1];
|
|
||||||
|
|
||||||
weights_[0] = 0.25;
|
const tetIndices& tetIs = cellTets[nearestTetI];
|
||||||
weights_[1] = 0.25;
|
|
||||||
weights_[2] = 0.25;
|
const face& f = pFaces[tetIs.face()];
|
||||||
weights_[3] = 0.25;
|
|
||||||
|
// Barycentric coordinates of the position, ignoring if the
|
||||||
|
// determinant is suitable. If not, the return from barycentric
|
||||||
|
// to weights_ is safe.
|
||||||
|
tetIs.tet(mesh).barycentric(position, weights_);
|
||||||
|
|
||||||
|
faceVertices_[0] = f[tetIs.faceBasePt()];
|
||||||
|
faceVertices_[1] = f[tetIs.facePtA()];
|
||||||
|
faceVertices_[2] = f[tetIs.facePtB()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -186,119 +142,112 @@ void Foam::cellPointWeight::findTriangle
|
|||||||
(
|
(
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label faceIndex
|
const label faceI
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Pout<< "\nbool Foam::cellPointWeight::findTriangle" << nl
|
Pout<< "\nbool Foam::cellPointWeight::findTriangle" << nl
|
||||||
<< "position = " << position << nl
|
<< "position = " << position << nl
|
||||||
<< "faceIndex = " << faceIndex << endl;
|
<< "faceI = " << faceI << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise closest triangle variables
|
List<tetIndices> faceTets = polyMeshTetDecomposition::faceTetIndices
|
||||||
scalar minUVClose = VGREAT;
|
(
|
||||||
label pointIClose = 0;
|
mesh,
|
||||||
|
mesh.faceOwner()[faceI],
|
||||||
|
faceI
|
||||||
|
);
|
||||||
|
|
||||||
// Decompose each face into triangles, making a tet when
|
const scalar faceAreaSqr = magSqr(mesh.faceAreas()[faceI]);
|
||||||
// augmented by the cell centre
|
|
||||||
const labelList& facePoints = mesh.faces()[faceIndex];
|
|
||||||
|
|
||||||
const scalar faceArea2 = magSqr(mesh.faceAreas()[faceIndex]);
|
const face& f = mesh.faces()[faceI];
|
||||||
|
|
||||||
label pointI = 1;
|
forAll(faceTets, tetI)
|
||||||
while ((pointI + 1) < facePoints.size())
|
|
||||||
{
|
{
|
||||||
// Cartesian co-ordinates of the triangle vertices
|
const tetIndices& tetIs = faceTets[tetI];
|
||||||
const vector& P1 = mesh.points()[facePoints[0]];
|
|
||||||
const vector& P2 = mesh.points()[facePoints[pointI]];
|
|
||||||
const vector& P3 = mesh.points()[facePoints[pointI + 1]];
|
|
||||||
|
|
||||||
// Direction vectors
|
List<scalar> triWeights(3);
|
||||||
vector v1 = position - P1;
|
|
||||||
const vector v2 = P2 - P1;
|
|
||||||
const vector v3 = P3 - P1;
|
|
||||||
|
|
||||||
// Plane normal
|
// Barycentric coordinates of the position
|
||||||
vector n = v2 ^ v3;
|
scalar det = tetIs.faceTri(mesh).barycentric(position, triWeights);
|
||||||
n /= mag(n);
|
|
||||||
|
|
||||||
// Remove any offset to plane
|
if (0.25*mag(det)/faceAreaSqr > tol)
|
||||||
v1 -= (n & v1)*v1;
|
|
||||||
|
|
||||||
// Helper variables
|
|
||||||
const scalar d12 = v1 & v2;
|
|
||||||
const scalar d13 = v1 & v3;
|
|
||||||
const scalar d22 = v2 & v2;
|
|
||||||
const scalar d23 = v2 & v3;
|
|
||||||
const scalar d33 = v3 & v3;
|
|
||||||
|
|
||||||
// Determinant of coefficients matrix
|
|
||||||
// Note: if det(A) = 0 the triangle is degenerate
|
|
||||||
const scalar detA = d22*d33 - d23*d23;
|
|
||||||
|
|
||||||
if (0.25*detA/faceArea2 > tol)
|
|
||||||
{
|
{
|
||||||
// Solve using Cramers' rule
|
const scalar& u = triWeights[0];
|
||||||
const scalar u = (d12*d33 - d23*d13)/detA;
|
const scalar& v = triWeights[1];
|
||||||
const scalar v = (d22*d13 - d12*d23)/detA;
|
|
||||||
|
|
||||||
// Check if point is in triangle
|
if
|
||||||
if ((u + tol > 0) && (v + tol > 0) && (u + v < 1 + tol))
|
(
|
||||||
|
(u + tol > 0)
|
||||||
|
&& (v + tol > 0)
|
||||||
|
&& (u + v < 1 + tol)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Indices of the cell vertices making up the triangle
|
// Weight[0] is for the cell centre.
|
||||||
faceVertices_[0] = facePoints[0];
|
weights_[0] = 0;
|
||||||
faceVertices_[1] = facePoints[pointI];
|
weights_[1] = triWeights[0];
|
||||||
faceVertices_[2] = facePoints[pointI + 1];
|
weights_[2] = triWeights[1];
|
||||||
|
weights_[3] = triWeights[2];
|
||||||
|
|
||||||
weights_[0] = u;
|
faceVertices_[0] = f[tetIs.faceBasePt()];
|
||||||
weights_[1] = v;
|
faceVertices_[1] = f[tetIs.facePtA()];;
|
||||||
weights_[2] = 1.0 - (u + v);
|
faceVertices_[2] = f[tetIs.facePtB()];;
|
||||||
weights_[3] = 0.0;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
scalar minU = mag(u);
|
|
||||||
scalar minV = mag(v);
|
|
||||||
if (minU > 1.0)
|
|
||||||
{
|
|
||||||
minU -= 1.0;
|
|
||||||
}
|
|
||||||
if (minV > 1.0)
|
|
||||||
{
|
|
||||||
minV -= 1.0;
|
|
||||||
}
|
|
||||||
const scalar minUV = mag(minU + minV);
|
|
||||||
|
|
||||||
if (minUV < minUVClose)
|
|
||||||
{
|
|
||||||
minUVClose = minUV;
|
|
||||||
pointIClose = pointI;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pointI++;
|
// A suitable point in a triangle was not found, find the nearest.
|
||||||
|
|
||||||
|
scalar minNearDist = VGREAT;
|
||||||
|
|
||||||
|
label nearestTetI = -1;
|
||||||
|
|
||||||
|
forAll(faceTets, tetI)
|
||||||
|
{
|
||||||
|
const tetIndices& tetIs = faceTets[tetI];
|
||||||
|
|
||||||
|
scalar nearDist = tetIs.faceTri(mesh).nearestPoint(position).distance();
|
||||||
|
|
||||||
|
if (nearDist < minNearDist)
|
||||||
|
{
|
||||||
|
minNearDist = nearDist;
|
||||||
|
|
||||||
|
nearestTetI = tetI;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
Pout<< "Foam::cellPointWeight::findTriangle"
|
Pout<< "cellPointWeight::findTriangle" << nl
|
||||||
<< "Triangle search failed; using closest triangle to point" << nl
|
<< " Triangle search failed; using closest tri to point "
|
||||||
<< " cell face: " << faceIndex << nl << endl;
|
<< position << nl
|
||||||
|
<< " face: "
|
||||||
|
<< faceI << nl
|
||||||
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indices of the cell vertices making up the triangle
|
const tetIndices& tetIs = faceTets[nearestTetI];
|
||||||
faceVertices_[0] = facePoints[0];
|
|
||||||
faceVertices_[1] = facePoints[pointIClose];
|
|
||||||
faceVertices_[2] = facePoints[pointIClose + 1];
|
|
||||||
|
|
||||||
weights_[0] = 1.0/3.0;
|
// Barycentric coordinates of the position, ignoring if the
|
||||||
weights_[1] = 1.0/3.0;
|
// determinant is suitable. If not, the return from barycentric
|
||||||
weights_[2] = 1.0/3.0;
|
// to triWeights is safe.
|
||||||
weights_[3] = 0.0;
|
|
||||||
|
List<scalar> triWeights(3);
|
||||||
|
|
||||||
|
tetIs.faceTri(mesh).barycentric(position, triWeights);
|
||||||
|
|
||||||
|
// Weight[0] is for the cell centre.
|
||||||
|
weights_[0] = 0;
|
||||||
|
weights_[1] = triWeights[0];
|
||||||
|
weights_[2] = triWeights[1];
|
||||||
|
weights_[3] = triWeights[2];
|
||||||
|
|
||||||
|
faceVertices_[0] = f[tetIs.faceBasePt()];
|
||||||
|
faceVertices_[1] = f[tetIs.facePtA()];
|
||||||
|
faceVertices_[2] = f[tetIs.facePtB()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -308,21 +257,23 @@ Foam::cellPointWeight::cellPointWeight
|
|||||||
(
|
(
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label cellIndex,
|
const label cellI,
|
||||||
const label faceIndex
|
const label faceI
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
cellIndex_(cellIndex)
|
cellI_(cellI),
|
||||||
|
weights_(4),
|
||||||
|
faceVertices_(3)
|
||||||
{
|
{
|
||||||
if (faceIndex < 0)
|
if (faceI < 0)
|
||||||
{
|
{
|
||||||
// Face data not supplied
|
// Face data not supplied
|
||||||
findTetrahedron(mesh, position, cellIndex);
|
findTetrahedron(mesh, position, cellI);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Face data supplied
|
// Face data supplied
|
||||||
findTriangle(mesh, position, faceIndex);
|
findTriangle(mesh, position, faceI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -55,13 +55,13 @@ protected:
|
|||||||
// Protected data
|
// Protected data
|
||||||
|
|
||||||
//- Cell index
|
//- Cell index
|
||||||
const label cellIndex_;
|
const label cellI_;
|
||||||
|
|
||||||
//- Weights applied to tet vertices
|
//- Weights applied to tet vertices
|
||||||
FixedList<scalar, 4> weights_;
|
List<scalar> weights_;
|
||||||
|
|
||||||
//- Face vertex indices
|
//- Face vertex indices
|
||||||
FixedList<label, 3> faceVertices_;
|
List<label> faceVertices_;
|
||||||
|
|
||||||
|
|
||||||
// Protected Member Functions
|
// Protected Member Functions
|
||||||
@ -70,14 +70,14 @@ protected:
|
|||||||
(
|
(
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label cellIndex
|
const label cellI
|
||||||
);
|
);
|
||||||
|
|
||||||
void findTriangle
|
void findTriangle
|
||||||
(
|
(
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label faceIndex
|
const label faceI
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -98,8 +98,8 @@ public:
|
|||||||
(
|
(
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label nCell,
|
const label cellI,
|
||||||
const label facei = -1
|
const label faceI = -1
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -108,17 +108,17 @@ public:
|
|||||||
//- Cell index
|
//- Cell index
|
||||||
inline label cell() const
|
inline label cell() const
|
||||||
{
|
{
|
||||||
return cellIndex_;
|
return cellI_;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- interpolation weights
|
//- interpolation weights
|
||||||
inline const FixedList<scalar, 4>& weights() const
|
inline const List<scalar>& weights() const
|
||||||
{
|
{
|
||||||
return weights_;
|
return weights_;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- interpolation addressing for points on face
|
//- interpolation addressing for points on face
|
||||||
inline const FixedList<label, 3>& faceVertices() const
|
inline const List<label>& faceVertices() const
|
||||||
{
|
{
|
||||||
return faceVertices_;
|
return faceVertices_;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,8 +82,17 @@ public:
|
|||||||
inline Type interpolate
|
inline Type interpolate
|
||||||
(
|
(
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label nCell,
|
const label cellI,
|
||||||
const label facei = -1
|
const label faceI = -1
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Interpolate field to the given point in the tetrahedron
|
||||||
|
// defined by the given indices.
|
||||||
|
inline Type interpolate
|
||||||
|
(
|
||||||
|
const vector& position,
|
||||||
|
const tetIndices& tetIs,
|
||||||
|
const label faceI = -1
|
||||||
) const;
|
) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -31,13 +31,13 @@ inline Type Foam::interpolationCellPoint<Type>::interpolate
|
|||||||
const cellPointWeight& cpw
|
const cellPointWeight& cpw
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const FixedList<scalar, 4>& weights = cpw.weights();
|
const List<scalar>& weights = cpw.weights();
|
||||||
const FixedList<label, 3>& faceVertices = cpw.faceVertices();
|
const List<label>& faceVertices = cpw.faceVertices();
|
||||||
|
|
||||||
Type t = psip_[faceVertices[0]]*weights[0];
|
Type t = this->psi_[cpw.cell()]*weights[0];
|
||||||
t += psip_[faceVertices[1]]*weights[1];
|
t += psip_[faceVertices[0]]*weights[1];
|
||||||
t += psip_[faceVertices[2]]*weights[2];
|
t += psip_[faceVertices[1]]*weights[2];
|
||||||
t += this->psi_[cpw.cell()]*weights[3];
|
t += psip_[faceVertices[2]]*weights[3];
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
@ -47,11 +47,66 @@ template<class Type>
|
|||||||
inline Type Foam::interpolationCellPoint<Type>::interpolate
|
inline Type Foam::interpolationCellPoint<Type>::interpolate
|
||||||
(
|
(
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label celli,
|
const label cellI,
|
||||||
const label facei
|
const label faceI
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
return interpolate(cellPointWeight(this->pMesh_, position, celli, facei));
|
return interpolate(cellPointWeight(this->pMesh_, position, cellI, faceI));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
inline Type Foam::interpolationCellPoint<Type>::interpolate
|
||||||
|
(
|
||||||
|
const vector& position,
|
||||||
|
const tetIndices& tetIs,
|
||||||
|
const label faceI
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Assumes that the position is consistent with the supplied
|
||||||
|
// tetIndices. Does not pay attention to whether or not faceI is
|
||||||
|
// supplied or not - the result will be essentially the same.
|
||||||
|
// Performs a consistency check, however.
|
||||||
|
|
||||||
|
if (faceI >= 0)
|
||||||
|
{
|
||||||
|
if (faceI != tetIs.face())
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"inline Type Foam::interpolationCellPoint<Type>::interpolate"
|
||||||
|
"("
|
||||||
|
"const vector& position, "
|
||||||
|
"const tetIndices& tetIs, "
|
||||||
|
"const label faceI"
|
||||||
|
") const"
|
||||||
|
)
|
||||||
|
<< "specified face " << faceI << " inconsistent with the face "
|
||||||
|
<< "stored by tetIndices: " << tetIs.face()
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<scalar> weights;
|
||||||
|
|
||||||
|
tetIs.tet(this->pMesh_).barycentric(position, weights);
|
||||||
|
|
||||||
|
const faceList& pFaces = this->pMesh_.faces();
|
||||||
|
|
||||||
|
const face& f = pFaces[tetIs.face()];
|
||||||
|
|
||||||
|
// Order of weights is the same as that of the vertices of the tet, i.e.
|
||||||
|
// cellCentre, faceBasePt, facePtA, facePtB.
|
||||||
|
|
||||||
|
Type t = this->psi_[tetIs.cell()]*weights[0];
|
||||||
|
|
||||||
|
t += psip_[f[tetIs.faceBasePt()]]*weights[1];
|
||||||
|
|
||||||
|
t += psip_[f[tetIs.facePtA()]]*weights[2];
|
||||||
|
|
||||||
|
t += psip_[f[tetIs.facePtB()]]*weights[3];
|
||||||
|
|
||||||
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -56,8 +56,8 @@ template<class Type>
|
|||||||
Type interpolationCellPointFace<Type>::interpolate
|
Type interpolationCellPointFace<Type>::interpolate
|
||||||
(
|
(
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label nCell,
|
const label cellI,
|
||||||
const label facei
|
const label faceI
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
Type ts[4];
|
Type ts[4];
|
||||||
@ -68,10 +68,10 @@ Type interpolationCellPointFace<Type>::interpolate
|
|||||||
Type t = pTraits<Type>::zero;
|
Type t = pTraits<Type>::zero;
|
||||||
|
|
||||||
// only use face information when the position is on a face
|
// only use face information when the position is on a face
|
||||||
if (facei < 0)
|
if (faceI < 0)
|
||||||
{
|
{
|
||||||
const vector& cellCentre = this->pMesh_.cellCentres()[nCell];
|
const vector& cellCentre = this->pMesh_.cellCentres()[cellI];
|
||||||
const labelList& cellFaces = this->pMesh_.cells()[nCell];
|
const labelList& cellFaces = this->pMesh_.cells()[cellI];
|
||||||
|
|
||||||
vector projection = position - cellCentre;
|
vector projection = position - cellCentre;
|
||||||
tetPoints[3] = cellCentre;
|
tetPoints[3] = cellCentre;
|
||||||
@ -85,9 +85,9 @@ Type interpolationCellPointFace<Type>::interpolate
|
|||||||
label closestFace = -1;
|
label closestFace = -1;
|
||||||
scalar minDistance = GREAT;
|
scalar minDistance = GREAT;
|
||||||
|
|
||||||
forAll(cellFaces, facei)
|
forAll(cellFaces, faceI)
|
||||||
{
|
{
|
||||||
label nFace = cellFaces[facei];
|
label nFace = cellFaces[faceI];
|
||||||
|
|
||||||
vector normal = this->pMeshFaceAreas_[nFace];
|
vector normal = this->pMeshFaceAreas_[nFace];
|
||||||
normal /= mag(normal);
|
normal /= mag(normal);
|
||||||
@ -160,10 +160,10 @@ Type interpolationCellPointFace<Type>::interpolate
|
|||||||
{
|
{
|
||||||
minDistance = GREAT;
|
minDistance = GREAT;
|
||||||
|
|
||||||
label facei = 0;
|
label faceI = 0;
|
||||||
while (facei < cellFaces.size() && !foundTet)
|
while (faceI < cellFaces.size() && !foundTet)
|
||||||
{
|
{
|
||||||
label nFace = cellFaces[facei];
|
label nFace = cellFaces[faceI];
|
||||||
if (nFace < this->pMeshFaceAreas_.size())
|
if (nFace < this->pMeshFaceAreas_.size())
|
||||||
{
|
{
|
||||||
foundTet = findTet
|
foundTet = findTet
|
||||||
@ -179,7 +179,7 @@ Type interpolationCellPointFace<Type>::interpolate
|
|||||||
minDistance
|
minDistance
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
facei++;
|
faceI++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,16 +217,16 @@ Type interpolationCellPointFace<Type>::interpolate
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
label patchi =
|
label patchI =
|
||||||
this->pMesh_.boundaryMesh().whichPatch(closestFace);
|
this->pMesh_.boundaryMesh().whichPatch(closestFace);
|
||||||
|
|
||||||
// If the boundary patch is not empty use the face value
|
// If the boundary patch is not empty use the face value
|
||||||
// else use the cell value
|
// else use the cell value
|
||||||
if (this->psi_.boundaryField()[patchi].size())
|
if (this->psi_.boundaryField()[patchI].size())
|
||||||
{
|
{
|
||||||
ts[2] = this->psi_.boundaryField()[patchi]
|
ts[2] = this->psi_.boundaryField()[patchI]
|
||||||
[
|
[
|
||||||
this->pMesh_.boundaryMesh()[patchi].whichFace
|
this->pMesh_.boundaryMesh()[patchI].whichFace
|
||||||
(
|
(
|
||||||
closestFace
|
closestFace
|
||||||
)
|
)
|
||||||
@ -234,11 +234,11 @@ Type interpolationCellPointFace<Type>::interpolate
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ts[2] = this->psi_[nCell];
|
ts[2] = this->psi_[cellI];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ts[3] = this->psi_[nCell];
|
ts[3] = this->psi_[cellI];
|
||||||
|
|
||||||
for (label n=0; n<4; n++)
|
for (label n=0; n<4; n++)
|
||||||
{
|
{
|
||||||
@ -251,9 +251,9 @@ Type interpolationCellPointFace<Type>::interpolate
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Info<< "interpolationCellPointFace<Type>::interpolate"
|
Info<< "interpolationCellPointFace<Type>::interpolate"
|
||||||
<< "(const vector&, const label nCell) const : "
|
<< "(const vector&, const label cellI) const : "
|
||||||
<< "search failed; using closest cellFace value" << endl
|
<< "search failed; using closest cellFace value" << endl
|
||||||
<< "cell number " << nCell << tab
|
<< "cell number " << cellI << tab
|
||||||
<< "position " << position << endl;
|
<< "position " << position << endl;
|
||||||
|
|
||||||
if (closestFace < psis_.size())
|
if (closestFace < psis_.size())
|
||||||
@ -262,16 +262,16 @@ Type interpolationCellPointFace<Type>::interpolate
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
label patchi =
|
label patchI =
|
||||||
this->pMesh_.boundaryMesh().whichPatch(closestFace);
|
this->pMesh_.boundaryMesh().whichPatch(closestFace);
|
||||||
|
|
||||||
// If the boundary patch is not empty use the face value
|
// If the boundary patch is not empty use the face value
|
||||||
// else use the cell value
|
// else use the cell value
|
||||||
if (this->psi_.boundaryField()[patchi].size())
|
if (this->psi_.boundaryField()[patchI].size())
|
||||||
{
|
{
|
||||||
t = this->psi_.boundaryField()[patchi]
|
t = this->psi_.boundaryField()[patchI]
|
||||||
[
|
[
|
||||||
this->pMesh_.boundaryMesh()[patchi].whichFace
|
this->pMesh_.boundaryMesh()[patchI].whichFace
|
||||||
(
|
(
|
||||||
closestFace
|
closestFace
|
||||||
)
|
)
|
||||||
@ -279,7 +279,7 @@ Type interpolationCellPointFace<Type>::interpolate
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t = this->psi_[nCell];
|
t = this->psi_[cellI];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,7 +289,7 @@ Type interpolationCellPointFace<Type>::interpolate
|
|||||||
bool foundTriangle = findTriangle
|
bool foundTriangle = findTriangle
|
||||||
(
|
(
|
||||||
position,
|
position,
|
||||||
facei,
|
faceI,
|
||||||
tetPointLabels,
|
tetPointLabels,
|
||||||
phi
|
phi
|
||||||
);
|
);
|
||||||
@ -304,48 +304,48 @@ Type interpolationCellPointFace<Type>::interpolate
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ... and the face value
|
// ... and the face value
|
||||||
if (facei < psis_.size())
|
if (faceI < psis_.size())
|
||||||
{
|
{
|
||||||
t += phi[2]*psis_[facei];
|
t += phi[2]*psis_[faceI];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
label patchi = this->pMesh_.boundaryMesh().whichPatch(facei);
|
label patchI = this->pMesh_.boundaryMesh().whichPatch(faceI);
|
||||||
|
|
||||||
// If the boundary patch is not empty use the face value
|
// If the boundary patch is not empty use the face value
|
||||||
// else use the cell value
|
// else use the cell value
|
||||||
if (this->psi_.boundaryField()[patchi].size())
|
if (this->psi_.boundaryField()[patchI].size())
|
||||||
{
|
{
|
||||||
t += phi[2]*this->psi_.boundaryField()[patchi]
|
t += phi[2]*this->psi_.boundaryField()[patchI]
|
||||||
[this->pMesh_.boundaryMesh()[patchi].whichFace(facei)];
|
[this->pMesh_.boundaryMesh()[patchI].whichFace(faceI)];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t += phi[2]*this->psi_[nCell];
|
t += phi[2]*this->psi_[cellI];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// use face value only
|
// use face value only
|
||||||
if (facei < psis_.size())
|
if (faceI < psis_.size())
|
||||||
{
|
{
|
||||||
t = psis_[facei];
|
t = psis_[faceI];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
label patchi = this->pMesh_.boundaryMesh().whichPatch(facei);
|
label patchI = this->pMesh_.boundaryMesh().whichPatch(faceI);
|
||||||
|
|
||||||
// If the boundary patch is not empty use the face value
|
// If the boundary patch is not empty use the face value
|
||||||
// else use the cell value
|
// else use the cell value
|
||||||
if (this->psi_.boundaryField()[patchi].size())
|
if (this->psi_.boundaryField()[patchI].size())
|
||||||
{
|
{
|
||||||
t = this->psi_.boundaryField()[patchi]
|
t = this->psi_.boundaryField()[patchI]
|
||||||
[this->pMesh_.boundaryMesh()[patchi].whichFace(facei)];
|
[this->pMesh_.boundaryMesh()[patchI].whichFace(faceI)];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t = this->psi_[nCell];
|
t = this->psi_[cellI];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -99,8 +99,8 @@ public:
|
|||||||
Type interpolate
|
Type interpolate
|
||||||
(
|
(
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label nCell,
|
const label cellI,
|
||||||
const label facei = -1
|
const label faceI = -1
|
||||||
) const;
|
) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -24,9 +24,6 @@ License
|
|||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "cellPointWeightWallModified.H"
|
#include "cellPointWeightWallModified.H"
|
||||||
#include "wallPolyPatch.H"
|
|
||||||
#include "polyMesh.H"
|
|
||||||
#include "polyBoundaryMesh.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -34,36 +31,30 @@ Foam::cellPointWeightWallModified::cellPointWeightWallModified
|
|||||||
(
|
(
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label cellIndex,
|
const label cellI,
|
||||||
const label faceIndex
|
const label faceI
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
cellPointWeight(mesh, position, cellIndex, faceIndex)
|
cellPointWeight(mesh, position, cellI, faceI)
|
||||||
{
|
{
|
||||||
if (faceIndex < 0)
|
// findTetrahedron or findTriangle will already have been called
|
||||||
{
|
// by the cellPointWeight constructor
|
||||||
findTetrahedron(mesh, position, cellIndex);
|
|
||||||
}
|
if (faceI >= 0)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
const polyBoundaryMesh& bm = mesh.boundaryMesh();
|
const polyBoundaryMesh& bm = mesh.boundaryMesh();
|
||||||
label patchI = bm.whichPatch(faceIndex);
|
label patchI = bm.whichPatch(faceI);
|
||||||
if (patchI != -1)
|
if (patchI != -1)
|
||||||
{
|
{
|
||||||
if (isA<wallPolyPatch>(bm[patchI]))
|
if (isA<wallPolyPatch>(bm[patchI]))
|
||||||
{
|
{
|
||||||
// Apply cell centre value wall faces
|
// Apply cell centre value wall faces
|
||||||
weights_[0] = 0.0;
|
weights_[0] = 1.0;
|
||||||
weights_[1] = 0.0;
|
weights_[1] = 0.0;
|
||||||
weights_[2] = 0.0;
|
weights_[2] = 0.0;
|
||||||
weights_[3] = 1.0;
|
weights_[3] = 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Interpolate
|
|
||||||
findTriangle(mesh, position, faceIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,9 @@ SourceFiles
|
|||||||
#define cellPointWeightWallModified_H
|
#define cellPointWeightWallModified_H
|
||||||
|
|
||||||
#include "cellPointWeight.H"
|
#include "cellPointWeight.H"
|
||||||
|
#include "wallPolyPatch.H"
|
||||||
|
#include "polyMesh.H"
|
||||||
|
#include "polyBoundaryMesh.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -61,8 +64,8 @@ public:
|
|||||||
(
|
(
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label nCell,
|
const label cellI,
|
||||||
const label facei = -1
|
const label faceI = -1
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -74,8 +74,17 @@ public:
|
|||||||
inline Type interpolate
|
inline Type interpolate
|
||||||
(
|
(
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label nCell,
|
const label cellI,
|
||||||
const label facei = -1
|
const label faceI = -1
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Interpolate field to the given point in the tetrahedron
|
||||||
|
// defined by the given indices.
|
||||||
|
inline Type interpolate
|
||||||
|
(
|
||||||
|
const vector& position,
|
||||||
|
const tetIndices& tetIs,
|
||||||
|
const label faceI = -1
|
||||||
) const;
|
) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -31,13 +31,13 @@ inline Type Foam::interpolationCellPointWallModified<Type>::interpolate
|
|||||||
const cellPointWeightWallModified& cpw
|
const cellPointWeightWallModified& cpw
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const FixedList<scalar, 4>& weights = cpw.weights();
|
const List<scalar>& weights = cpw.weights();
|
||||||
const FixedList<label, 3>& faceVertices = cpw.faceVertices();
|
const List<label>& faceVertices = cpw.faceVertices();
|
||||||
|
|
||||||
Type t = this->psip_[faceVertices[0]]*weights[0];
|
Type t = this->psi_[cpw.cell()]*weights[0];
|
||||||
t += this->psip_[faceVertices[1]]*weights[1];
|
t += this->psip_[faceVertices[0]]*weights[1];
|
||||||
t += this->psip_[faceVertices[2]]*weights[2];
|
t += this->psip_[faceVertices[1]]*weights[2];
|
||||||
t += this->psi_[cpw.cell()]*weights[3];
|
t += this->psip_[faceVertices[2]]*weights[3];
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
@ -47,22 +47,74 @@ template<class Type>
|
|||||||
inline Type Foam::interpolationCellPointWallModified<Type>::interpolate
|
inline Type Foam::interpolationCellPointWallModified<Type>::interpolate
|
||||||
(
|
(
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label celli,
|
const label cellI,
|
||||||
const label facei
|
const label faceI
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
return
|
return interpolate
|
||||||
interpolate
|
|
||||||
(
|
(
|
||||||
cellPointWeightWallModified
|
cellPointWeightWallModified
|
||||||
(
|
(
|
||||||
this->pMesh_,
|
this->pMesh_,
|
||||||
position,
|
position,
|
||||||
celli,
|
cellI,
|
||||||
facei
|
faceI
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
inline Type Foam::interpolationCellPointWallModified<Type>::interpolate
|
||||||
|
(
|
||||||
|
const vector& position,
|
||||||
|
const tetIndices& tetIs,
|
||||||
|
const label faceI
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
if (faceI >= 0)
|
||||||
|
{
|
||||||
|
if (faceI != tetIs.face())
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"inline Type "
|
||||||
|
"Foam::interpolationCellPointWallModifie<Type>::interpolate"
|
||||||
|
"("
|
||||||
|
"const vector& position, "
|
||||||
|
"const tetIndices& tetIs, "
|
||||||
|
"const label faceI"
|
||||||
|
") const"
|
||||||
|
)
|
||||||
|
<< "specified face " << faceI << " inconsistent with the face "
|
||||||
|
<< "stored by tetIndices: " << tetIs.face()
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
const polyBoundaryMesh& bm = this->pMesh_.boundaryMesh();
|
||||||
|
label patchI = bm.whichPatch(faceI);
|
||||||
|
|
||||||
|
if (patchI != -1)
|
||||||
|
{
|
||||||
|
if (isA<wallPolyPatch>(bm[patchI]))
|
||||||
|
{
|
||||||
|
Type t = this->psi_[tetIs.cell()];
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the wall face selection did not return, then use the normal
|
||||||
|
// interpolate method
|
||||||
|
|
||||||
|
return interpolationCellPoint<Type>::interpolate
|
||||||
|
(
|
||||||
|
position,
|
||||||
|
tetIs,
|
||||||
|
faceI
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -81,8 +81,8 @@ public:
|
|||||||
inline Type interpolate
|
inline Type interpolate
|
||||||
(
|
(
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label nCell,
|
const label cellI,
|
||||||
const label facei = -1
|
const label faceI = -1
|
||||||
) const;
|
) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -39,13 +39,13 @@ template<class Type>
|
|||||||
inline Type Foam::interpolationPoint<Type>::interpolate
|
inline Type Foam::interpolationPoint<Type>::interpolate
|
||||||
(
|
(
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label celli,
|
const label cellI,
|
||||||
const label facei
|
const label faceI
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
return interpolate
|
return interpolate
|
||||||
(
|
(
|
||||||
pointMVCWeight(this->pMesh_, position, celli, facei)
|
pointMVCWeight(this->pMesh_, position, cellI, faceI)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -119,8 +119,8 @@ public:
|
|||||||
(
|
(
|
||||||
const polyMesh& mesh,
|
const polyMesh& mesh,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label nCell,
|
const label cellI,
|
||||||
const label facei = -1
|
const label faceI = -1
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,41 @@ License
|
|||||||
#include "mapPolyMesh.H"
|
#include "mapPolyMesh.H"
|
||||||
#include "Time.H"
|
#include "Time.H"
|
||||||
#include "OFstream.H"
|
#include "OFstream.H"
|
||||||
|
#include "wallPolyPatch.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class ParticleType>
|
||||||
|
const Foam::scalar Foam::Cloud<ParticleType>::trackingCorrectionTol = 1e-5;
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class ParticleType>
|
||||||
|
void Foam::Cloud<ParticleType>::calcCellWallFaces() const
|
||||||
|
{
|
||||||
|
cellWallFacesPtr_.reset(new PackedBoolList(pMesh().nCells(), false));
|
||||||
|
|
||||||
|
PackedBoolList& cellWallFaces = cellWallFacesPtr_();
|
||||||
|
|
||||||
|
const polyBoundaryMesh& patches = pMesh().boundaryMesh();
|
||||||
|
|
||||||
|
forAll(patches, patchI)
|
||||||
|
{
|
||||||
|
if (isA<wallPolyPatch>(patches[patchI]))
|
||||||
|
{
|
||||||
|
const polyPatch& patch = patches[patchI];
|
||||||
|
|
||||||
|
const labelList& pFaceCells = patch.faceCells();
|
||||||
|
|
||||||
|
forAll(pFaceCells, pFCI)
|
||||||
|
{
|
||||||
|
cellWallFaces[pFaceCells[pFCI]] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -43,7 +78,11 @@ Foam::Cloud<ParticleType>::Cloud
|
|||||||
cloud(pMesh),
|
cloud(pMesh),
|
||||||
IDLList<ParticleType>(),
|
IDLList<ParticleType>(),
|
||||||
polyMesh_(pMesh),
|
polyMesh_(pMesh),
|
||||||
particleCount_(0)
|
particleCount_(0),
|
||||||
|
labels_(),
|
||||||
|
cellTree_(),
|
||||||
|
nTrackingRescues_(),
|
||||||
|
cellWallFacesPtr_()
|
||||||
{
|
{
|
||||||
IDLList<ParticleType>::operator=(particles);
|
IDLList<ParticleType>::operator=(particles);
|
||||||
}
|
}
|
||||||
@ -60,7 +99,11 @@ Foam::Cloud<ParticleType>::Cloud
|
|||||||
cloud(pMesh, cloudName),
|
cloud(pMesh, cloudName),
|
||||||
IDLList<ParticleType>(),
|
IDLList<ParticleType>(),
|
||||||
polyMesh_(pMesh),
|
polyMesh_(pMesh),
|
||||||
particleCount_(0)
|
particleCount_(0),
|
||||||
|
labels_(),
|
||||||
|
cellTree_(),
|
||||||
|
nTrackingRescues_(),
|
||||||
|
cellWallFacesPtr_()
|
||||||
{
|
{
|
||||||
IDLList<ParticleType>::operator=(particles);
|
IDLList<ParticleType>::operator=(particles);
|
||||||
}
|
}
|
||||||
@ -68,6 +111,250 @@ Foam::Cloud<ParticleType>::Cloud
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class ParticleType>
|
||||||
|
void Foam::Cloud<ParticleType>::findCellFacePt
|
||||||
|
(
|
||||||
|
const point& pt,
|
||||||
|
label& cellI,
|
||||||
|
label& tetFaceI,
|
||||||
|
label& tetPtI
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
cellI = -1;
|
||||||
|
tetFaceI = -1;
|
||||||
|
tetPtI = -1;
|
||||||
|
|
||||||
|
const indexedOctree<treeDataCell>& tree = cellTree();
|
||||||
|
|
||||||
|
// Find nearest cell to the point
|
||||||
|
|
||||||
|
pointIndexHit info = tree.findNearest(pt, sqr(GREAT));
|
||||||
|
|
||||||
|
if (info.hit())
|
||||||
|
{
|
||||||
|
label nearestCellI = tree.shapes().cellLabels()[info.index()];
|
||||||
|
|
||||||
|
// Check the nearest cell to see if the point is inside.
|
||||||
|
findFacePt(nearestCellI, pt, tetFaceI, tetPtI);
|
||||||
|
|
||||||
|
if (tetFaceI != -1)
|
||||||
|
{
|
||||||
|
// Point was in the nearest cell
|
||||||
|
|
||||||
|
cellI = nearestCellI;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check the other possible cells that the point may be in
|
||||||
|
|
||||||
|
labelList testCells = tree.findIndices(pt);
|
||||||
|
|
||||||
|
forAll(testCells, pCI)
|
||||||
|
{
|
||||||
|
label testCellI = tree.shapes().cellLabels()[testCells[pCI]];
|
||||||
|
|
||||||
|
if (testCellI == nearestCellI)
|
||||||
|
{
|
||||||
|
// Don't retest the nearest cell
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the test cell to see if the point is inside.
|
||||||
|
findFacePt(testCellI, pt, tetFaceI, tetPtI);
|
||||||
|
|
||||||
|
if (tetFaceI != -1)
|
||||||
|
{
|
||||||
|
// Point was in the test cell
|
||||||
|
|
||||||
|
cellI = testCellI;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"void Foam::Cloud<ParticleType>::findCellFacePt"
|
||||||
|
"("
|
||||||
|
"const point& pt, "
|
||||||
|
"label& cellI, "
|
||||||
|
"label& tetFaceI, "
|
||||||
|
"label& tetPtI"
|
||||||
|
") const"
|
||||||
|
) << "Did not find nearest cell in search tree."
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ParticleType>
|
||||||
|
void Foam::Cloud<ParticleType>::findFacePt
|
||||||
|
(
|
||||||
|
label cellI,
|
||||||
|
const point& pt,
|
||||||
|
label& tetFaceI,
|
||||||
|
label& tetPtI
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
tetFaceI = -1;
|
||||||
|
tetPtI = -1;
|
||||||
|
|
||||||
|
List<tetIndices> cellTets = polyMeshTetDecomposition::cellTetIndices
|
||||||
|
(
|
||||||
|
polyMesh_,
|
||||||
|
cellI
|
||||||
|
);
|
||||||
|
|
||||||
|
forAll(cellTets, tetI)
|
||||||
|
{
|
||||||
|
const tetIndices& cellTetIs = cellTets[tetI];
|
||||||
|
|
||||||
|
if (inTet(pt, cellTetIs.tet(polyMesh_)))
|
||||||
|
{
|
||||||
|
tetFaceI = cellTetIs.face();
|
||||||
|
tetPtI = cellTetIs.tetPt();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ParticleType>
|
||||||
|
bool Foam::Cloud<ParticleType>::inTet
|
||||||
|
(
|
||||||
|
const point& pt,
|
||||||
|
const tetPointRef& tet
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// For robustness, assuming that the point is in the tet unless
|
||||||
|
// "definitively" shown otherwise by obtaining a positive dot
|
||||||
|
// product greater than a tolerance of SMALL.
|
||||||
|
|
||||||
|
// The tet is defined: tet(Cc, tetBasePt, pA, pB) where the normal
|
||||||
|
// vectors and base points for the half-space planes are:
|
||||||
|
// area[0] = tet.Sa();
|
||||||
|
// area[1] = tet.Sb();
|
||||||
|
// area[2] = tet.Sc();
|
||||||
|
// area[3] = tet.Sd();
|
||||||
|
// planeBase[0] = tetBasePt = tet.b()
|
||||||
|
// planeBase[1] = ptA = tet.c()
|
||||||
|
// planeBase[2] = tetBasePt = tet.b()
|
||||||
|
// planeBase[3] = tetBasePt = tet.b()
|
||||||
|
|
||||||
|
vector n = vector::zero;
|
||||||
|
|
||||||
|
{
|
||||||
|
// 0, a
|
||||||
|
const point& basePt = tet.b();
|
||||||
|
|
||||||
|
n = tet.Sa();
|
||||||
|
n /= (mag(n) + VSMALL);
|
||||||
|
|
||||||
|
if (((pt - basePt) & n) > SMALL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// 1, b
|
||||||
|
const point& basePt = tet.c();
|
||||||
|
|
||||||
|
n = tet.Sb();
|
||||||
|
n /= (mag(n) + VSMALL);
|
||||||
|
|
||||||
|
if (((pt - basePt) & n) > SMALL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// 2, c
|
||||||
|
const point& basePt = tet.b();
|
||||||
|
|
||||||
|
n = tet.Sc();
|
||||||
|
n /= (mag(n) + VSMALL);
|
||||||
|
|
||||||
|
if (((pt - basePt) & n) > SMALL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// 3, d
|
||||||
|
const point& basePt = tet.b();
|
||||||
|
|
||||||
|
n = tet.Sd();
|
||||||
|
n /= (mag(n) + VSMALL);
|
||||||
|
|
||||||
|
if (((pt - basePt) & n) > SMALL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ParticleType>
|
||||||
|
const Foam::indexedOctree<Foam::treeDataCell>&
|
||||||
|
Foam::Cloud<ParticleType>::cellTree() const
|
||||||
|
{
|
||||||
|
if (cellTree_.empty())
|
||||||
|
{
|
||||||
|
treeBoundBox overallBb(polyMesh_.points());
|
||||||
|
|
||||||
|
Random rndGen(261782);
|
||||||
|
|
||||||
|
overallBb = overallBb.extend(rndGen, 1E-4);
|
||||||
|
overallBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
|
||||||
|
overallBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
|
||||||
|
|
||||||
|
cellTree_.reset
|
||||||
|
(
|
||||||
|
new indexedOctree<treeDataCell>
|
||||||
|
(
|
||||||
|
treeDataCell
|
||||||
|
(
|
||||||
|
false, // not cache bb
|
||||||
|
polyMesh_
|
||||||
|
),
|
||||||
|
overallBb,
|
||||||
|
8, // maxLevel
|
||||||
|
10, // leafsize
|
||||||
|
3.0 // duplicity
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cellTree_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ParticleType>
|
||||||
|
const Foam::PackedBoolList& Foam::Cloud<ParticleType>::cellHasWallFaces()
|
||||||
|
const
|
||||||
|
{
|
||||||
|
if (!cellWallFacesPtr_.valid())
|
||||||
|
{
|
||||||
|
calcCellWallFaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
return cellWallFacesPtr_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class ParticleType>
|
template<class ParticleType>
|
||||||
Foam::label Foam::Cloud<ParticleType>::getNewParticleID() const
|
Foam::label Foam::Cloud<ParticleType>::getNewParticleID() const
|
||||||
{
|
{
|
||||||
@ -131,6 +418,9 @@ void Foam::Cloud<ParticleType>::move(TrackingData& td)
|
|||||||
pIter().stepFraction() = 0;
|
pIter().stepFraction() = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset nTrackingRescues
|
||||||
|
nTrackingRescues_ = 0;
|
||||||
|
|
||||||
// While there are particles to transfer
|
// While there are particles to transfer
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@ -162,29 +452,29 @@ void Foam::Cloud<ParticleType>::move(TrackingData& td)
|
|||||||
{
|
{
|
||||||
// If we are running in parallel and the particle is on a
|
// If we are running in parallel and the particle is on a
|
||||||
// boundary face
|
// boundary face
|
||||||
if (Pstream::parRun() && p.facei_ >= pMesh().nInternalFaces())
|
if (Pstream::parRun() && p.faceI_ >= pMesh().nInternalFaces())
|
||||||
{
|
{
|
||||||
label patchi = pbm.whichPatch(p.facei_);
|
label patchI = pbm.whichPatch(p.faceI_);
|
||||||
|
|
||||||
// ... and the face is on a processor patch
|
// ... and the face is on a processor patch
|
||||||
// prepare it for transfer
|
// prepare it for transfer
|
||||||
if (procPatchIndices[patchi] != -1)
|
if (procPatchIndices[patchI] != -1)
|
||||||
{
|
{
|
||||||
label n = neighbourProcIndices
|
label n = neighbourProcIndices
|
||||||
[
|
[
|
||||||
refCast<const processorPolyPatch>
|
refCast<const processorPolyPatch>
|
||||||
(
|
(
|
||||||
pbm[patchi]
|
pbm[patchI]
|
||||||
).neighbProcNo()
|
).neighbProcNo()
|
||||||
];
|
];
|
||||||
|
|
||||||
p.prepareForParallelTransfer(patchi, td);
|
p.prepareForParallelTransfer(patchI, td);
|
||||||
|
|
||||||
particleTransferLists[n].append(this->remove(&p));
|
particleTransferLists[n].append(this->remove(&p));
|
||||||
|
|
||||||
patchIndexTransferLists[n].append
|
patchIndexTransferLists[n].append
|
||||||
(
|
(
|
||||||
procPatchNeighbours[patchi]
|
procPatchNeighbours[patchI]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,15 +560,22 @@ void Foam::Cloud<ParticleType>::move(TrackingData& td)
|
|||||||
{
|
{
|
||||||
ParticleType& newp = newpIter();
|
ParticleType& newp = newpIter();
|
||||||
|
|
||||||
label patchi = procPatches[receivePatchIndex[pI++]];
|
label patchI = procPatches[receivePatchIndex[pI++]];
|
||||||
|
|
||||||
newp.correctAfterParallelTransfer(patchi, td);
|
newp.correctAfterParallelTransfer(patchI, td);
|
||||||
|
|
||||||
addParticle(newParticles.remove(&newp));
|
addParticle(newParticles.remove(&newp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reduce(nTrackingRescues_, sumOp<label>());
|
||||||
|
|
||||||
|
if (nTrackingRescues_ > 0)
|
||||||
|
{
|
||||||
|
Info<< nTrackingRescues_ << " tracking rescue corrections" << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -294,24 +591,30 @@ void Foam::Cloud<ParticleType>::autoMap(const mapPolyMesh& mapper)
|
|||||||
const labelList& reverseCellMap = mapper.reverseCellMap();
|
const labelList& reverseCellMap = mapper.reverseCellMap();
|
||||||
const labelList& reverseFaceMap = mapper.reverseFaceMap();
|
const labelList& reverseFaceMap = mapper.reverseFaceMap();
|
||||||
|
|
||||||
|
// Reset stored data that relies on the mesh
|
||||||
|
cellTree_.clear();
|
||||||
|
cellWallFacesPtr_.clear();
|
||||||
|
|
||||||
forAllIter(typename Cloud<ParticleType>, *this, pIter)
|
forAllIter(typename Cloud<ParticleType>, *this, pIter)
|
||||||
{
|
{
|
||||||
if (reverseCellMap[pIter().celli_] >= 0)
|
if (reverseCellMap[pIter().cellI_] >= 0)
|
||||||
{
|
{
|
||||||
pIter().celli_ = reverseCellMap[pIter().celli_];
|
pIter().cellI_ = reverseCellMap[pIter().cellI_];
|
||||||
|
|
||||||
if (pIter().facei_ >= 0 && reverseFaceMap[pIter().facei_] >= 0)
|
if (pIter().faceI_ >= 0 && reverseFaceMap[pIter().faceI_] >= 0)
|
||||||
{
|
{
|
||||||
pIter().facei_ = reverseFaceMap[pIter().facei_];
|
pIter().faceI_ = reverseFaceMap[pIter().faceI_];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pIter().facei_ = -1;
|
pIter().faceI_ = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pIter().initCellFacePt();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
label trackStartCell = mapper.mergedCell(pIter().celli_);
|
label trackStartCell = mapper.mergedCell(pIter().cellI_);
|
||||||
|
|
||||||
if (trackStartCell < 0)
|
if (trackStartCell < 0)
|
||||||
{
|
{
|
||||||
@ -319,9 +622,14 @@ void Foam::Cloud<ParticleType>::autoMap(const mapPolyMesh& mapper)
|
|||||||
}
|
}
|
||||||
|
|
||||||
vector p = pIter().position();
|
vector p = pIter().position();
|
||||||
|
|
||||||
const_cast<vector&>(pIter().position()) =
|
const_cast<vector&>(pIter().position()) =
|
||||||
polyMesh_.cellCentres()[trackStartCell];
|
polyMesh_.cellCentres()[trackStartCell];
|
||||||
|
|
||||||
pIter().stepFraction() = 0;
|
pIter().stepFraction() = 0;
|
||||||
|
|
||||||
|
pIter().initCellFacePt();
|
||||||
|
|
||||||
pIter().track(p);
|
pIter().track(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,11 @@ SourceFiles
|
|||||||
#include "IOField.H"
|
#include "IOField.H"
|
||||||
#include "IOFieldField.H"
|
#include "IOFieldField.H"
|
||||||
#include "polyMesh.H"
|
#include "polyMesh.H"
|
||||||
|
#include "indexedOctree.H"
|
||||||
|
#include "treeDataCell.H"
|
||||||
|
#include "tetPointRef.H"
|
||||||
|
#include "polyMeshTetDecomposition.H"
|
||||||
|
#include "PackedBoolList.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -78,15 +83,28 @@ class Cloud
|
|||||||
//- Overall count of particles ever created. Never decreases.
|
//- Overall count of particles ever created. Never decreases.
|
||||||
mutable label particleCount_;
|
mutable label particleCount_;
|
||||||
|
|
||||||
//- Temporary storage for addressing. Used in findFaces.
|
//- Temporary storage for addressing. Used in findTris.
|
||||||
mutable DynamicList<label> labels_;
|
mutable DynamicList<label> labels_;
|
||||||
|
|
||||||
|
//- Search tree to allow spatial tet searching
|
||||||
|
mutable autoPtr<indexedOctree<treeDataCell> > cellTree_;
|
||||||
|
|
||||||
|
//- Count of how many tracking rescue corrections have been
|
||||||
|
// applied
|
||||||
|
mutable label nTrackingRescues_;
|
||||||
|
|
||||||
|
//- Does the cell have wall faces
|
||||||
|
mutable autoPtr<PackedBoolList> cellWallFacesPtr_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Initialise cloud on IO constructor
|
//- Initialise cloud on IO constructor
|
||||||
void initCloud(const bool checkClass);
|
void initCloud(const bool checkClass);
|
||||||
|
|
||||||
|
//- Find all cells which have wall faces
|
||||||
|
void calcCellWallFaces() const;
|
||||||
|
|
||||||
//- Read cloud properties dictionary
|
//- Read cloud properties dictionary
|
||||||
void readCloudUniformProperties();
|
void readCloudUniformProperties();
|
||||||
|
|
||||||
@ -115,6 +133,10 @@ public:
|
|||||||
//- Name of cloud properties dictionary
|
//- Name of cloud properties dictionary
|
||||||
static word cloudPropertiesName;
|
static word cloudPropertiesName;
|
||||||
|
|
||||||
|
//- Fraction of distance to tet centre to move a particle to
|
||||||
|
// 'rescue' it from a tracking problem
|
||||||
|
static const scalar trackingCorrectionTol;
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
@ -163,27 +185,27 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- Is this global face an internal face?
|
//- Is this global face an internal face?
|
||||||
bool internalFace(const label facei) const
|
bool internalFace(const label faceI) const
|
||||||
{
|
{
|
||||||
return polyMesh_.isInternalFace(facei);
|
return polyMesh_.isInternalFace(faceI);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Is this global face a boundary face?
|
//- Is this global face a boundary face?
|
||||||
bool boundaryFace(const label facei) const
|
bool boundaryFace(const label faceI) const
|
||||||
{
|
{
|
||||||
return !internalFace(facei);
|
return !internalFace(faceI);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Which patch is this global face on
|
//- Which patch is this global face on
|
||||||
label facePatch(const label facei) const
|
label facePatch(const label faceI) const
|
||||||
{
|
{
|
||||||
return polyMesh_.boundaryMesh().whichPatch(facei);
|
return polyMesh_.boundaryMesh().whichPatch(faceI);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Which face of this patch is this global face
|
//- Which face of this patch is this global face
|
||||||
label patchFace(const label patchi, const label facei) const
|
label patchFace(const label patchI, const label faceI) const
|
||||||
{
|
{
|
||||||
return polyMesh_.boundaryMesh()[patchi].whichFace(facei);
|
return polyMesh_.boundaryMesh()[patchI].whichFace(faceI);
|
||||||
}
|
}
|
||||||
|
|
||||||
label size() const
|
label size() const
|
||||||
@ -191,6 +213,61 @@ public:
|
|||||||
return IDLList<ParticleType>::size();
|
return IDLList<ParticleType>::size();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//- Find the cell, tetFaceI and tetPtI for the given
|
||||||
|
// position
|
||||||
|
void findCellFacePt
|
||||||
|
(
|
||||||
|
const point& pt,
|
||||||
|
label& cellI,
|
||||||
|
label& tetFaceI,
|
||||||
|
label& tetPtI
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Find the tetFaceI and tetPtI for the given position in
|
||||||
|
// the supplied cell, tetFaceI and tetPtI = -1 if not
|
||||||
|
// found
|
||||||
|
void findFacePt
|
||||||
|
(
|
||||||
|
label cellI,
|
||||||
|
const point& pt,
|
||||||
|
label& tetFaceI,
|
||||||
|
label& tetPtI
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Test if the given position is inside the give tet
|
||||||
|
bool inTet
|
||||||
|
(
|
||||||
|
const point& pt,
|
||||||
|
const tetPointRef& tet
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Build (if necessary) and return the cell search tree
|
||||||
|
const indexedOctree<treeDataCell>& cellTree() const;
|
||||||
|
|
||||||
|
//- Return nTrackingRescues
|
||||||
|
label nTrackingRescues() const
|
||||||
|
{
|
||||||
|
return nTrackingRescues_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Increment the nTrackingRescues counter
|
||||||
|
void trackingRescue() const
|
||||||
|
{
|
||||||
|
nTrackingRescues_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Whether each cell has any wall faces (demand driven data)
|
||||||
|
const PackedBoolList& cellHasWallFaces() const;
|
||||||
|
|
||||||
|
//- Switch to specify if particles of the cloud can return
|
||||||
|
// non-zero wall distance values. By default, assume
|
||||||
|
// that they can't (default for wallImpactDistance in
|
||||||
|
// Particle is 0.0).
|
||||||
|
virtual bool hasWallImpactDistance() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Iterators
|
// Iterators
|
||||||
|
|
||||||
|
|||||||
@ -126,6 +126,13 @@ void Foam::Cloud<ParticleType>::initCloud(const bool checkClass)
|
|||||||
<< " " << ioP.path() << nl
|
<< " " << ioP.path() << nl
|
||||||
<< " assuming the initial cloud contains 0 particles." << endl;
|
<< " assuming the initial cloud contains 0 particles." << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forAllIter(typename Cloud<ParticleType>, *this, pIter)
|
||||||
|
{
|
||||||
|
ParticleType& p = pIter();
|
||||||
|
|
||||||
|
p.initCellFacePt();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -140,7 +147,11 @@ Foam::Cloud<ParticleType>::Cloud
|
|||||||
:
|
:
|
||||||
cloud(pMesh),
|
cloud(pMesh),
|
||||||
polyMesh_(pMesh),
|
polyMesh_(pMesh),
|
||||||
particleCount_(0)
|
particleCount_(0),
|
||||||
|
labels_(),
|
||||||
|
cellTree_(),
|
||||||
|
nTrackingRescues_(),
|
||||||
|
cellWallFacesPtr_()
|
||||||
{
|
{
|
||||||
initCloud(checkClass);
|
initCloud(checkClass);
|
||||||
}
|
}
|
||||||
@ -156,7 +167,11 @@ Foam::Cloud<ParticleType>::Cloud
|
|||||||
:
|
:
|
||||||
cloud(pMesh, cloudName),
|
cloud(pMesh, cloudName),
|
||||||
polyMesh_(pMesh),
|
polyMesh_(pMesh),
|
||||||
particleCount_(0)
|
particleCount_(0),
|
||||||
|
labels_(),
|
||||||
|
cellTree_(),
|
||||||
|
nTrackingRescues_(),
|
||||||
|
cellWallFacesPtr_()
|
||||||
{
|
{
|
||||||
initCloud(checkClass);
|
initCloud(checkClass);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude
|
||||||
|
|
||||||
|
LIB_LIBS = \
|
||||||
|
-lmeshTools
|
||||||
|
|||||||
@ -29,73 +29,20 @@ License
|
|||||||
#include "symmetryPolyPatch.H"
|
#include "symmetryPolyPatch.H"
|
||||||
#include "cyclicPolyPatch.H"
|
#include "cyclicPolyPatch.H"
|
||||||
#include "processorPolyPatch.H"
|
#include "processorPolyPatch.H"
|
||||||
#include "wallPolyPatch.H"
|
|
||||||
#include "transform.H"
|
#include "transform.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class ParticleType>
|
|
||||||
void Foam::Particle<ParticleType>::findFaces
|
|
||||||
(
|
|
||||||
const vector& position,
|
|
||||||
DynamicList<label>& faceList
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
const polyMesh& mesh = cloud_.polyMesh_;
|
|
||||||
const labelList& faces = mesh.cells()[celli_];
|
|
||||||
const vector& C = mesh.cellCentres()[celli_];
|
|
||||||
|
|
||||||
faceList.clear();
|
|
||||||
forAll(faces, i)
|
|
||||||
{
|
|
||||||
label facei = faces[i];
|
|
||||||
scalar lam = lambda(C, position, facei);
|
|
||||||
|
|
||||||
if ((lam > 0) && (lam < 1.0))
|
|
||||||
{
|
|
||||||
faceList.append(facei);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class ParticleType>
|
|
||||||
void Foam::Particle<ParticleType>::findFaces
|
|
||||||
(
|
|
||||||
const vector& position,
|
|
||||||
const label celli,
|
|
||||||
const scalar stepFraction,
|
|
||||||
DynamicList<label>& faceList
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
const polyMesh& mesh = cloud_.pMesh();
|
|
||||||
const labelList& faces = mesh.cells()[celli];
|
|
||||||
const vector& C = mesh.cellCentres()[celli];
|
|
||||||
|
|
||||||
faceList.clear();
|
|
||||||
forAll(faces, i)
|
|
||||||
{
|
|
||||||
label facei = faces[i];
|
|
||||||
scalar lam = lambda(C, position, facei, stepFraction);
|
|
||||||
|
|
||||||
if ((lam > 0) && (lam < 1.0))
|
|
||||||
{
|
|
||||||
faceList.append(facei);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class ParticleType>
|
template<class ParticleType>
|
||||||
template<class TrackData>
|
template<class TrackData>
|
||||||
void Foam::Particle<ParticleType>::prepareForParallelTransfer
|
void Foam::Particle<ParticleType>::prepareForParallelTransfer
|
||||||
(
|
(
|
||||||
const label patchi,
|
const label patchI,
|
||||||
TrackData& td
|
TrackData& td
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Convert the face index to be local to the processor patch
|
// Convert the face index to be local to the processor patch
|
||||||
facei_ = patchFace(patchi, facei_);
|
faceI_ = patchFace(patchI, faceI_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -103,15 +50,15 @@ template<class ParticleType>
|
|||||||
template<class TrackData>
|
template<class TrackData>
|
||||||
void Foam::Particle<ParticleType>::correctAfterParallelTransfer
|
void Foam::Particle<ParticleType>::correctAfterParallelTransfer
|
||||||
(
|
(
|
||||||
const label patchi,
|
const label patchI,
|
||||||
TrackData& td
|
TrackData& td
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const processorPolyPatch& ppp =
|
const processorPolyPatch& ppp =
|
||||||
refCast<const processorPolyPatch>
|
refCast<const processorPolyPatch>
|
||||||
(cloud_.pMesh().boundaryMesh()[patchi]);
|
(cloud_.pMesh().boundaryMesh()[patchI]);
|
||||||
|
|
||||||
celli_ = ppp.faceCells()[facei_];
|
cellI_ = ppp.faceCells()[faceI_];
|
||||||
|
|
||||||
if (!ppp.parallel())
|
if (!ppp.parallel())
|
||||||
{
|
{
|
||||||
@ -123,7 +70,7 @@ void Foam::Particle<ParticleType>::correctAfterParallelTransfer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const tensor& T = ppp.forwardT()[facei_];
|
const tensor& T = ppp.forwardT()[faceI_];
|
||||||
transformPosition(T);
|
transformPosition(T);
|
||||||
static_cast<ParticleType&>(*this).transformProperties(T);
|
static_cast<ParticleType&>(*this).transformProperties(T);
|
||||||
}
|
}
|
||||||
@ -140,23 +87,48 @@ void Foam::Particle<ParticleType>::correctAfterParallelTransfer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
position_ -= ppp.separation()[facei_];
|
position_ -= ppp.separation()[faceI_];
|
||||||
static_cast<ParticleType&>(*this).transformProperties
|
static_cast<ParticleType&>(*this).transformProperties
|
||||||
(
|
(
|
||||||
-ppp.separation()[facei_]
|
-ppp.separation()[faceI_]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tetFaceI_ = faceI_ + ppp.start();
|
||||||
|
|
||||||
|
// Faces either side of a coupled patch have matched base indices,
|
||||||
|
// tetPtI is specified relative to the base point, already and
|
||||||
|
// opposite circulation directions by design, so if the vertices
|
||||||
|
// are:
|
||||||
|
// source:
|
||||||
|
// face (a b c d e f)
|
||||||
|
// fPtI 0 1 2 3 4 5
|
||||||
|
// +
|
||||||
|
// destination:
|
||||||
|
// face (a f e d c b)
|
||||||
|
// fPtI 0 1 2 3 4 5
|
||||||
|
// +
|
||||||
|
// where a is the base point of the face are matching , and we
|
||||||
|
// have fPtI = 1 on the source processor face, i.e. vertex b, then
|
||||||
|
// this because of the face circulation direction change, vertex c
|
||||||
|
// is the characterising point on the destination processor face,
|
||||||
|
// giving the destination fPtI as:
|
||||||
|
// fPtI_d = f.size() - 1 - fPtI_s = 6 - 1 - 1 = 4
|
||||||
|
// This relationship can be verified for other points and sizes of
|
||||||
|
// face.
|
||||||
|
|
||||||
|
tetPtI_ = cloud_.polyMesh_.faces()[tetFaceI_].size() - 1 - tetPtI_;
|
||||||
|
|
||||||
// Reset the face index for the next tracking operation
|
// Reset the face index for the next tracking operation
|
||||||
if (stepFraction_ > (1.0 - SMALL))
|
if (stepFraction_ > (1.0 - SMALL))
|
||||||
{
|
{
|
||||||
stepFraction_ = 1.0;
|
stepFraction_ = 1.0;
|
||||||
facei_ = -1;
|
faceI_ = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
facei_ += ppp.start();
|
faceI_ += ppp.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,27 +140,55 @@ Foam::Particle<ParticleType>::Particle
|
|||||||
(
|
(
|
||||||
const Cloud<ParticleType>& cloud,
|
const Cloud<ParticleType>& cloud,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label celli
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
cloud_(cloud),
|
cloud_(cloud),
|
||||||
position_(position),
|
position_(position),
|
||||||
celli_(celli),
|
cellI_(cellI),
|
||||||
facei_(-1),
|
faceI_(-1),
|
||||||
stepFraction_(0.0),
|
stepFraction_(0.0),
|
||||||
|
tetFaceI_(tetFaceI),
|
||||||
|
tetPtI_(tetPtI),
|
||||||
origProc_(Pstream::myProcNo()),
|
origProc_(Pstream::myProcNo()),
|
||||||
origId_(cloud_.getNewParticleID())
|
origId_(cloud_.getNewParticleID())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ParticleType>
|
||||||
|
Foam::Particle<ParticleType>::Particle
|
||||||
|
(
|
||||||
|
const Cloud<ParticleType>& cloud,
|
||||||
|
const vector& position,
|
||||||
|
const label cellI
|
||||||
|
)
|
||||||
|
:
|
||||||
|
cloud_(cloud),
|
||||||
|
position_(position),
|
||||||
|
cellI_(cellI),
|
||||||
|
faceI_(-1),
|
||||||
|
stepFraction_(0.0),
|
||||||
|
tetFaceI_(-1),
|
||||||
|
tetPtI_(-1),
|
||||||
|
origProc_(Pstream::myProcNo()),
|
||||||
|
origId_(cloud_.getNewParticleID())
|
||||||
|
{
|
||||||
|
initCellFacePt();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class ParticleType>
|
template<class ParticleType>
|
||||||
Foam::Particle<ParticleType>::Particle(const Particle<ParticleType>& p)
|
Foam::Particle<ParticleType>::Particle(const Particle<ParticleType>& p)
|
||||||
:
|
:
|
||||||
cloud_(p.cloud_),
|
cloud_(p.cloud_),
|
||||||
position_(p.position_),
|
position_(p.position_),
|
||||||
celli_(p.celli_),
|
cellI_(p.cellI_),
|
||||||
facei_(p.facei_),
|
faceI_(p.faceI_),
|
||||||
stepFraction_(p.stepFraction_),
|
stepFraction_(p.stepFraction_),
|
||||||
|
tetFaceI_(p.tetFaceI_),
|
||||||
|
tetPtI_(p.tetPtI_),
|
||||||
origProc_(p.origProc_),
|
origProc_(p.origProc_),
|
||||||
origId_(p.origId_)
|
origId_(p.origId_)
|
||||||
{}
|
{}
|
||||||
@ -204,7 +204,7 @@ Foam::label Foam::Particle<ParticleType>::track
|
|||||||
TrackData& td
|
TrackData& td
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
facei_ = -1;
|
faceI_ = -1;
|
||||||
|
|
||||||
// Tracks to endPosition or stop on boundary
|
// Tracks to endPosition or stop on boundary
|
||||||
while (!onBoundary() && stepFraction_ < 1.0 - SMALL)
|
while (!onBoundary() && stepFraction_ < 1.0 - SMALL)
|
||||||
@ -212,7 +212,7 @@ Foam::label Foam::Particle<ParticleType>::track
|
|||||||
stepFraction_ += trackToFace(endPosition, td)*(1.0 - stepFraction_);
|
stepFraction_ += trackToFace(endPosition, td)*(1.0 - stepFraction_);
|
||||||
}
|
}
|
||||||
|
|
||||||
return facei_;
|
return faceI_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -224,6 +224,7 @@ Foam::label Foam::Particle<ParticleType>::track(const vector& endPosition)
|
|||||||
return track(endPosition, dummyTd);
|
return track(endPosition, dummyTd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class ParticleType>
|
template<class ParticleType>
|
||||||
template<class TrackData>
|
template<class TrackData>
|
||||||
Foam::scalar Foam::Particle<ParticleType>::trackToFace
|
Foam::scalar Foam::Particle<ParticleType>::trackToFace
|
||||||
@ -234,92 +235,270 @@ Foam::scalar Foam::Particle<ParticleType>::trackToFace
|
|||||||
{
|
{
|
||||||
const polyMesh& mesh = cloud_.polyMesh_;
|
const polyMesh& mesh = cloud_.polyMesh_;
|
||||||
|
|
||||||
DynamicList<label>& faces = cloud_.labels_;
|
const faceList& pFaces = mesh.faces();
|
||||||
findFaces(endPosition, faces);
|
const pointField& pPts = mesh.points();
|
||||||
|
const vectorField& pC = mesh.cellCentres();
|
||||||
|
|
||||||
|
faceI_ = -1;
|
||||||
|
|
||||||
facei_ = -1;
|
|
||||||
scalar trackFraction = 0.0;
|
scalar trackFraction = 0.0;
|
||||||
|
|
||||||
if (faces.empty()) // inside cell
|
// Minimum tetrahedron decomposition of each cell of the mesh into
|
||||||
{
|
// using the cell centre, base point on face, and further two
|
||||||
trackFraction = 1.0;
|
// points on the face. For each face of n points, there are n - 2
|
||||||
position_ = endPosition;
|
// tets generated.
|
||||||
}
|
|
||||||
else // hit face
|
|
||||||
{
|
|
||||||
scalar lambdaMin = GREAT;
|
|
||||||
|
|
||||||
if (faces.size() == 1)
|
// The points for each tet are organised to match those used in the
|
||||||
|
// tetrahedron class, supplying them in the order:
|
||||||
|
// Cc, basePt, pA, pB
|
||||||
|
// where:
|
||||||
|
// + Cc is the cell centre;
|
||||||
|
// + basePt is the base point on the face;
|
||||||
|
// + pA and pB are the remaining points on the face, such that
|
||||||
|
// the circulation, {basePt, pA, pB} produces a positive
|
||||||
|
// normal by the right-hand rule. pA and pB are chosen from
|
||||||
|
// tetPtI_ do accomplish this depending if the cell owns the
|
||||||
|
// face, tetPtI_ is the vertex that characterises the tet, and
|
||||||
|
// is the first vertex on the tet when circulating around the
|
||||||
|
// face. Therefore, the same tetPtI represents the same face
|
||||||
|
// triangle for both the owner and neighbour cell.
|
||||||
|
//
|
||||||
|
// Each tet has its four triangles represented in the same order:
|
||||||
|
// 0) tri joining a tet to the tet across the face in next cell.
|
||||||
|
// This is the triangle opposite Cc.
|
||||||
|
// 1) tri joining a tet to the tet that is in the same cell, but
|
||||||
|
// belongs to the face that shares the edge of the current face
|
||||||
|
// that doesn't contain basePt. This is the triangle opposite
|
||||||
|
// basePt.
|
||||||
|
|
||||||
|
// 2) tri joining a tet to the tet that is in the same cell, but
|
||||||
|
// belongs to the face that shares the tet-edge (basePt - pB).
|
||||||
|
// This may be on the same face, or a different one. This is
|
||||||
|
// the triangle opposite basePt. This is the triangle opposite
|
||||||
|
// pA.
|
||||||
|
|
||||||
|
// 4) tri joining a tet to the tet that is in the same cell, but
|
||||||
|
// belongs to the face that shares the tet-edge (basePt - pA).
|
||||||
|
// This may be on the same face, or a different one. This is
|
||||||
|
// the triangle opposite basePt. This is the triangle opposite
|
||||||
|
// pA.
|
||||||
|
|
||||||
|
// Which tri (0..3) of the tet has been crossed
|
||||||
|
label triI = -1;
|
||||||
|
|
||||||
|
// Determine which face was actually crossed. lambdaMin < SMALL
|
||||||
|
// is considered a trigger for a tracking correction towards the
|
||||||
|
// current tet centre.
|
||||||
|
scalar lambdaMin = VGREAT;
|
||||||
|
|
||||||
|
DynamicList<label>& tris = cloud_.labels_;
|
||||||
|
|
||||||
|
// Tet indices that will be set by hitWallFaces if a wall face is
|
||||||
|
// to be hit, or are set when any wall tri of a tet is hit.
|
||||||
|
// Carries the description of the tet on which the cell face has
|
||||||
|
// been hit. For the case of being set in hitWallFaces, this may
|
||||||
|
// be a different tet to the one that the particle occupies.
|
||||||
|
tetIndices faceHitTetIs;
|
||||||
|
|
||||||
|
do
|
||||||
{
|
{
|
||||||
lambdaMin = lambda(position_, endPosition, faces[0], stepFraction_);
|
if (triI != -1)
|
||||||
facei_ = faces[0];
|
{
|
||||||
|
// Change tet ownership because a tri face has been crossed
|
||||||
|
tetNeighbour(triI);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Foam::face& f = pFaces[tetFaceI_];
|
||||||
|
|
||||||
|
bool own = (mesh.faceOwner()[tetFaceI_] == cellI_);
|
||||||
|
|
||||||
|
label tetBasePtI = mesh.tetBasePtIs()[tetFaceI_];
|
||||||
|
|
||||||
|
label basePtI = f[tetBasePtI];
|
||||||
|
|
||||||
|
label facePtI = (tetPtI_ + tetBasePtI) % f.size();
|
||||||
|
label otherFacePtI = f.fcIndex(facePtI);
|
||||||
|
|
||||||
|
label fPtAI = -1;
|
||||||
|
label fPtBI = -1;
|
||||||
|
|
||||||
|
if (own)
|
||||||
|
{
|
||||||
|
fPtAI = facePtI;
|
||||||
|
fPtBI = otherFacePtI;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If the particle has to cross more than one cell to reach the
|
fPtAI = otherFacePtI;
|
||||||
// endPosition, we check which way to go.
|
fPtBI = facePtI;
|
||||||
// If one of the faces is a boundary face and the particle is
|
}
|
||||||
// outside, we choose the boundary face.
|
|
||||||
// The particle is outside if one of the lambda's is > 1 or < 0
|
tetPointRef tet
|
||||||
forAll(faces, i)
|
(
|
||||||
|
pC[cellI_],
|
||||||
|
pPts[basePtI],
|
||||||
|
pPts[f[fPtAI]],
|
||||||
|
pPts[f[fPtBI]]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (lambdaMin < SMALL)
|
||||||
{
|
{
|
||||||
scalar lam =
|
// Apply tracking correction towards tet centre
|
||||||
lambda(position_, endPosition, faces[i], stepFraction_);
|
|
||||||
|
position_ +=
|
||||||
|
Cloud<ParticleType>::trackingCorrectionTol
|
||||||
|
*(tet.centre() - position_);
|
||||||
|
|
||||||
|
cloud_.trackingRescue();
|
||||||
|
|
||||||
|
return trackFraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (triI != -1 && mesh.moving())
|
||||||
|
{
|
||||||
|
// Mesh motion requires stepFraction to be correct for
|
||||||
|
// each tracking portion, so trackToFace must return after
|
||||||
|
// every lambda calculation.
|
||||||
|
return trackFraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedList<vector, 4> tetAreas;
|
||||||
|
|
||||||
|
tetAreas[0] = tet.Sa();
|
||||||
|
tetAreas[1] = tet.Sb();
|
||||||
|
tetAreas[2] = tet.Sc();
|
||||||
|
tetAreas[3] = tet.Sd();
|
||||||
|
|
||||||
|
FixedList<label, 4> tetPlaneBasePtIs;
|
||||||
|
|
||||||
|
tetPlaneBasePtIs[0] = basePtI;
|
||||||
|
tetPlaneBasePtIs[1] = f[fPtAI];
|
||||||
|
tetPlaneBasePtIs[2] = basePtI;
|
||||||
|
tetPlaneBasePtIs[3] = basePtI;
|
||||||
|
|
||||||
|
findTris(endPosition, tris, tet, tetAreas, tetPlaneBasePtIs);
|
||||||
|
|
||||||
|
// Reset variables for new track
|
||||||
|
triI = -1;
|
||||||
|
lambdaMin = VGREAT;
|
||||||
|
|
||||||
|
// Sets a value for lambdaMin and faceI_ if a wall face is hit
|
||||||
|
// by the track.
|
||||||
|
hitWallFaces(position_, endPosition, lambdaMin, faceHitTetIs);
|
||||||
|
|
||||||
|
// Did not hit any tet tri faces, and no wall face has been
|
||||||
|
// found to hit.
|
||||||
|
if (tris.empty() && faceI_ < 0)
|
||||||
|
{
|
||||||
|
position_ = endPosition;
|
||||||
|
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Loop over all found tris and see if any of them find a
|
||||||
|
// lambda value smaller than that found for a wall face.
|
||||||
|
forAll(tris, i)
|
||||||
|
{
|
||||||
|
label tI = tris[i];
|
||||||
|
|
||||||
|
scalar lam = tetLambda
|
||||||
|
(
|
||||||
|
position_,
|
||||||
|
endPosition,
|
||||||
|
triI,
|
||||||
|
tetAreas[tI],
|
||||||
|
tetPlaneBasePtIs[tI],
|
||||||
|
cellI_,
|
||||||
|
tetFaceI_,
|
||||||
|
tetPtI_
|
||||||
|
);
|
||||||
|
|
||||||
if (lam < lambdaMin)
|
if (lam < lambdaMin)
|
||||||
{
|
{
|
||||||
lambdaMin = lam;
|
lambdaMin = lam;
|
||||||
facei_ = faces[i];
|
|
||||||
|
triI = tI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool internalFace = cloud_.internalFace(facei_);
|
if (triI == 0)
|
||||||
|
{
|
||||||
|
// This must be a cell face crossing
|
||||||
|
faceI_ = tetFaceI_;
|
||||||
|
|
||||||
// For warped faces the particle can be 'outside' the cell.
|
// Set the faceHitTetIs to those for the current tet in case a
|
||||||
// This will yield a lambda larger than 1, or smaller than 0
|
// wall interaction is required with the cell face
|
||||||
// For values < 0, the particle travels away from the cell
|
faceHitTetIs = tetIndices
|
||||||
// and we don't move the particle, only change cell.
|
(
|
||||||
// For values larger than 1, we move the particle to endPosition only.
|
cellI_,
|
||||||
if (lambdaMin > 0.0)
|
tetFaceI_,
|
||||||
|
tetBasePtI,
|
||||||
|
fPtAI,
|
||||||
|
fPtBI,
|
||||||
|
tetPtI_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (triI > 0)
|
||||||
|
{
|
||||||
|
// A tri was found to be crossed before a wall face was hit (if any)
|
||||||
|
faceI_ = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The particle can be 'outside' the tet. This will yield a
|
||||||
|
// lambda larger than 1, or smaller than 0. For values < 0,
|
||||||
|
// the particle travels away from the tet and we don't move
|
||||||
|
// the particle, only change tet/cell. For values larger than
|
||||||
|
// 1, we move the particle to endPosition before the tet/cell
|
||||||
|
// change.
|
||||||
|
if (lambdaMin > SMALL)
|
||||||
{
|
{
|
||||||
if (lambdaMin <= 1.0)
|
if (lambdaMin <= 1.0)
|
||||||
{
|
{
|
||||||
trackFraction = lambdaMin;
|
trackFraction += lambdaMin*(1 - trackFraction);
|
||||||
position_ += trackFraction*(endPosition - position_);
|
|
||||||
|
position_ += lambdaMin*(endPosition - position_);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
trackFraction = 1.0;
|
trackFraction = 1.0;
|
||||||
|
|
||||||
position_ = endPosition;
|
position_ = endPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (static_cast<ParticleType&>(*this).softImpact())
|
else
|
||||||
{
|
{
|
||||||
// Soft-sphere particles can travel outside the domain
|
// Set lambdaMin to zero to force a towards-tet-centre
|
||||||
// but we don't use lambda since this the particle
|
// correction.
|
||||||
// is going away from face
|
lambdaMin = 0.0;
|
||||||
trackFraction = 1.0;
|
|
||||||
position_ = endPosition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// change cell
|
} while (faceI_ < 0);
|
||||||
if (internalFace) // Internal face
|
|
||||||
|
if (cloud_.internalFace(faceI_))
|
||||||
{
|
{
|
||||||
if (celli_ == mesh.faceOwner()[facei_])
|
// Change tet ownership because a tri face has been crossed,
|
||||||
|
// in general this is:
|
||||||
|
// tetNeighbour(triI);
|
||||||
|
// but triI must be 0;
|
||||||
|
// No modifications are required for triI = 0, no call required to
|
||||||
|
// tetNeighbour(0);
|
||||||
|
|
||||||
|
if (cellI_ == mesh.faceOwner()[faceI_])
|
||||||
{
|
{
|
||||||
celli_ = mesh.faceNeighbour()[facei_];
|
cellI_ = mesh.faceNeighbour()[faceI_];
|
||||||
}
|
}
|
||||||
else if (celli_ == mesh.faceNeighbour()[facei_])
|
else if (cellI_ == mesh.faceNeighbour()[faceI_])
|
||||||
{
|
{
|
||||||
celli_ = mesh.faceOwner()[facei_];
|
cellI_ = mesh.faceOwner()[faceI_];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FatalErrorIn
|
FatalErrorIn
|
||||||
(
|
(
|
||||||
"Particle::trackToFace(const vector&, TrackData&)"
|
"Particle::trackToFace(const vector&, TrackData&)"
|
||||||
)<< "addressing failure" << nl
|
) << "addressing failure" << nl
|
||||||
<< abort(FatalError);
|
<< abort(FatalError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -327,24 +506,31 @@ Foam::scalar Foam::Particle<ParticleType>::trackToFace
|
|||||||
{
|
{
|
||||||
ParticleType& p = static_cast<ParticleType&>(*this);
|
ParticleType& p = static_cast<ParticleType&>(*this);
|
||||||
|
|
||||||
// Soft-sphere algorithm ignores the boundary
|
label origFaceI = faceI_;
|
||||||
if (p.softImpact())
|
label patchI = patch(faceI_);
|
||||||
{
|
|
||||||
trackFraction = 1.0;
|
|
||||||
position_ = endPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
label origFacei = facei_;
|
// No action taken for tetPtI_ for tetFaceI_ here, handled by
|
||||||
label patchi = patch(facei_);
|
// patch interaction call or later during processor transfer.
|
||||||
|
|
||||||
if (!p.hitPatch(mesh.boundaryMesh()[patchi], td, patchi))
|
if
|
||||||
|
(
|
||||||
|
!p.hitPatch
|
||||||
|
(
|
||||||
|
mesh.boundaryMesh()[patchI],
|
||||||
|
td,
|
||||||
|
patchI,
|
||||||
|
trackFraction,
|
||||||
|
faceHitTetIs
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// Did patch interaction model switch patches?
|
// Did patch interaction model switch patches?
|
||||||
if (facei_ != origFacei)
|
if (faceI_ != origFaceI)
|
||||||
{
|
{
|
||||||
patchi = patch(facei_);
|
patchI = patch(faceI_);
|
||||||
}
|
}
|
||||||
const polyPatch& patch = mesh.boundaryMesh()[patchi];
|
|
||||||
|
const polyPatch& patch = mesh.boundaryMesh()[patchI];
|
||||||
|
|
||||||
if (isA<wedgePolyPatch>(patch))
|
if (isA<wedgePolyPatch>(patch))
|
||||||
{
|
{
|
||||||
@ -378,7 +564,7 @@ Foam::scalar Foam::Particle<ParticleType>::trackToFace
|
|||||||
{
|
{
|
||||||
p.hitWallPatch
|
p.hitWallPatch
|
||||||
(
|
(
|
||||||
static_cast<const wallPolyPatch&>(patch), td
|
static_cast<const wallPolyPatch&>(patch), td, faceHitTetIs
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -387,22 +573,76 @@ Foam::scalar Foam::Particle<ParticleType>::trackToFace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lambdaMin < SMALL)
|
||||||
|
{
|
||||||
|
// Apply tracking correction towards tet centre.
|
||||||
|
// Generate current tet to find centre to apply correction.
|
||||||
|
|
||||||
|
tetPointRef tet = currentTet();
|
||||||
|
|
||||||
|
position_ +=
|
||||||
|
Cloud<ParticleType>::trackingCorrectionTol
|
||||||
|
*(tet.centre() - position_);
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
cloud_.hasWallImpactDistance()
|
||||||
|
&& !cloud_.internalFace(faceHitTetIs.face())
|
||||||
|
&& cloud_.cellHasWallFaces()[faceHitTetIs.cell()]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const polyBoundaryMesh& patches = mesh.boundaryMesh();
|
||||||
|
|
||||||
|
label fI = faceHitTetIs.face();
|
||||||
|
|
||||||
|
label patchI = patches.patchID()[fI - mesh.nInternalFaces()];
|
||||||
|
|
||||||
|
if (isA<wallPolyPatch>(patches[patchI]))
|
||||||
|
{
|
||||||
|
// In the case of collision with a wall where there is
|
||||||
|
// a non-zero wallImpactDistance, it is possible for
|
||||||
|
// there to be a tracking correction required to bring
|
||||||
|
// the particle into the domain, but the position of
|
||||||
|
// the particle is further from the wall than the tet
|
||||||
|
// centre, in which case the normal correction can be
|
||||||
|
// counter-productive, i.e. pushes the particle
|
||||||
|
// further out of the domain. In this case it is the
|
||||||
|
// position that hit the wall that is in need of a
|
||||||
|
// rescue correction.
|
||||||
|
|
||||||
|
triPointRef wallTri = faceHitTetIs.faceTri(mesh);
|
||||||
|
|
||||||
|
tetPointRef wallTet = faceHitTetIs.tet(mesh);
|
||||||
|
|
||||||
|
vector nHat = wallTri.normal();
|
||||||
|
nHat /= mag(nHat);
|
||||||
|
|
||||||
|
const ParticleType& p = static_cast<const ParticleType&>(*this);
|
||||||
|
|
||||||
|
scalar r = p.wallImpactDistance(nHat);
|
||||||
|
|
||||||
|
// Removing (approximately) the wallTri normal
|
||||||
|
// component of the existing correction, to avoid the
|
||||||
|
// situation where the existing correction in the wall
|
||||||
|
// normal direction is larger towards the wall than
|
||||||
|
// the new correction is away from it.
|
||||||
|
position_ +=
|
||||||
|
Cloud<ParticleType>::trackingCorrectionTol
|
||||||
|
*(
|
||||||
|
(wallTet.centre() - (position_ + r*nHat))
|
||||||
|
- (nHat & (tet.centre() - position_))*nHat
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the trackFraction = 0 something went wrong.
|
cloud_.trackingRescue();
|
||||||
// Either the particle is flipping back and forth across a face perhaps
|
|
||||||
// due to velocity interpolation errors or it is in a "hole" in the mesh
|
|
||||||
// caused by face warpage.
|
|
||||||
// In both cases resolve the positional ambiguity by moving the particle
|
|
||||||
// slightly towards the cell-centre.
|
|
||||||
if (trackFraction < SMALL)
|
|
||||||
{
|
|
||||||
position_ += 1.0e-3*(mesh.cellCentres()[celli_] - position_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return trackFraction;
|
return trackFraction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class ParticleType>
|
template<class ParticleType>
|
||||||
Foam::scalar Foam::Particle<ParticleType>::trackToFace
|
Foam::scalar Foam::Particle<ParticleType>::trackToFace
|
||||||
(
|
(
|
||||||
@ -413,6 +653,7 @@ Foam::scalar Foam::Particle<ParticleType>::trackToFace
|
|||||||
return trackToFace(endPosition, dummyTd);
|
return trackToFace(endPosition, dummyTd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class ParticleType>
|
template<class ParticleType>
|
||||||
void Foam::Particle<ParticleType>::transformPosition(const tensor& T)
|
void Foam::Particle<ParticleType>::transformPosition(const tensor& T)
|
||||||
{
|
{
|
||||||
@ -436,7 +677,9 @@ bool Foam::Particle<ParticleType>::hitPatch
|
|||||||
(
|
(
|
||||||
const polyPatch&,
|
const polyPatch&,
|
||||||
TrackData&,
|
TrackData&,
|
||||||
const label
|
const label,
|
||||||
|
const scalar,
|
||||||
|
const tetIndices&
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -451,7 +694,17 @@ void Foam::Particle<ParticleType>::hitWedgePatch
|
|||||||
TrackData&
|
TrackData&
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
vector nf = wpp.faceAreas()[wpp.whichFace(facei_)];
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"void Foam::Particle<ParticleType>::hitWedgePatch"
|
||||||
|
"("
|
||||||
|
"const wedgePolyPatch& wpp, "
|
||||||
|
"TrackData&"
|
||||||
|
")"
|
||||||
|
) << "Hitting a wedge patch should not be possible."
|
||||||
|
<< abort(FatalError);
|
||||||
|
|
||||||
|
vector nf = normal();
|
||||||
nf /= mag(nf);
|
nf /= mag(nf);
|
||||||
|
|
||||||
static_cast<ParticleType&>(*this).transformProperties(I - 2.0*nf*nf);
|
static_cast<ParticleType&>(*this).transformProperties(I - 2.0*nf*nf);
|
||||||
@ -466,7 +719,7 @@ void Foam::Particle<ParticleType>::hitSymmetryPatch
|
|||||||
TrackData&
|
TrackData&
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
vector nf = spp.faceAreas()[spp.whichFace(facei_)];
|
vector nf = normal();
|
||||||
nf /= mag(nf);
|
nf /= mag(nf);
|
||||||
|
|
||||||
static_cast<ParticleType&>(*this).transformProperties(I - 2.0*nf*nf);
|
static_cast<ParticleType&>(*this).transformProperties(I - 2.0*nf*nf);
|
||||||
@ -481,11 +734,16 @@ void Foam::Particle<ParticleType>::hitCyclicPatch
|
|||||||
TrackData&
|
TrackData&
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// label patchFacei_ = cpp.whichFace(facei_);
|
// label patchFaceI_ = cpp.whichFace(faceI_);
|
||||||
|
|
||||||
facei_ = cpp.transformGlobalFace(facei_);
|
faceI_ = cpp.transformGlobalFace(faceI_);
|
||||||
|
|
||||||
celli_ = cloud_.polyMesh_.faceOwner()[facei_];
|
cellI_ = cloud_.polyMesh_.faceOwner()[faceI_];
|
||||||
|
|
||||||
|
tetFaceI_ = faceI_;
|
||||||
|
|
||||||
|
// See note in correctAfterParallelTransfer for tetPtI_ addressing.
|
||||||
|
tetPtI_ = cloud_.polyMesh_.faces()[tetFaceI_].size() - 1 - tetPtI_;
|
||||||
|
|
||||||
// Now the particle is on the receiving side
|
// Now the particle is on the receiving side
|
||||||
|
|
||||||
@ -522,7 +780,8 @@ template<class TrackData>
|
|||||||
void Foam::Particle<ParticleType>::hitWallPatch
|
void Foam::Particle<ParticleType>::hitWallPatch
|
||||||
(
|
(
|
||||||
const wallPolyPatch& spp,
|
const wallPolyPatch& spp,
|
||||||
TrackData&
|
TrackData&,
|
||||||
|
const tetIndices&
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,10 @@ Description
|
|||||||
#include "faceList.H"
|
#include "faceList.H"
|
||||||
#include "typeInfo.H"
|
#include "typeInfo.H"
|
||||||
#include "OFstream.H"
|
#include "OFstream.H"
|
||||||
|
#include "tetPointRef.H"
|
||||||
|
#include "FixedList.H"
|
||||||
|
#include "polyMeshTetDecomposition.H"
|
||||||
|
#include "wallPolyPatch.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -125,14 +129,23 @@ protected:
|
|||||||
vector position_;
|
vector position_;
|
||||||
|
|
||||||
//- Index of the cell it is in
|
//- Index of the cell it is in
|
||||||
label celli_;
|
label cellI_;
|
||||||
|
|
||||||
//- Face index if the particle is on a face otherwise -1
|
//- Face index if the particle is on a face otherwise -1
|
||||||
label facei_;
|
label faceI_;
|
||||||
|
|
||||||
//- Fraction of time-step completed
|
//- Fraction of time-step completed
|
||||||
scalar stepFraction_;
|
scalar stepFraction_;
|
||||||
|
|
||||||
|
//- Index of the face that owns the decomposed tet that the
|
||||||
|
// particle is in
|
||||||
|
label tetFaceI_;
|
||||||
|
|
||||||
|
//- Index of the point on the face that defines the decomposed
|
||||||
|
// tet that the particle is in. Relative to the face base
|
||||||
|
// point.
|
||||||
|
label tetPtI_;
|
||||||
|
|
||||||
//- Originating processor id
|
//- Originating processor id
|
||||||
label origProc_;
|
label origProc_;
|
||||||
|
|
||||||
@ -142,54 +155,82 @@ protected:
|
|||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Return the 'lambda' value for the position, p, on the face,
|
//- Find the tet tri faces between position and tet centre
|
||||||
// where, p = from + lamda*(to - from)
|
inline void findTris
|
||||||
// for non-static meshes
|
(
|
||||||
inline scalar lambda
|
const vector& position,
|
||||||
|
DynamicList<label>& faceList,
|
||||||
|
const tetPointRef& tet,
|
||||||
|
const FixedList<vector, 4>& tetAreas,
|
||||||
|
const FixedList<label, 4>& tetPlaneBasePtIs
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Find the lambda value for the line to-from across the
|
||||||
|
// given tri face, where p = from + lambda*(to - from)
|
||||||
|
inline scalar tetLambda
|
||||||
(
|
(
|
||||||
const vector& from,
|
const vector& from,
|
||||||
const vector& to,
|
const vector& to,
|
||||||
const label facei,
|
const label triI,
|
||||||
const scalar stepFraction
|
const vector& tetArea,
|
||||||
|
const label tetPlaneBasePtI,
|
||||||
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Return the 'lambda' value for the position, p, on the face,
|
//- Find the lambda value for a moving tri face
|
||||||
// where, p = from + lamda*(to - from)
|
inline scalar movingTetLambda
|
||||||
// for static meshes
|
|
||||||
inline scalar lambda
|
|
||||||
(
|
(
|
||||||
const vector& from,
|
const vector& from,
|
||||||
const vector& to,
|
const vector& to,
|
||||||
const label facei
|
const label triI,
|
||||||
|
const vector& tetArea,
|
||||||
|
const label tetPlaneBasePtI,
|
||||||
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Find the faces between position and cell centre
|
//- Modify the tet owner data by crossing triI
|
||||||
void findFaces
|
inline void tetNeighbour(label triI);
|
||||||
(
|
|
||||||
const vector& position,
|
|
||||||
DynamicList<label>& faceList
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Find the faces between position and cell centre
|
//- Cross the from the given face across the given edge of the
|
||||||
void findFaces
|
// given cell to find the resulting face and tetPtI
|
||||||
|
inline void crossEdgeConnectedFace
|
||||||
(
|
(
|
||||||
const vector& position,
|
const label& cellI,
|
||||||
const label celli,
|
label& tetFaceI,
|
||||||
const scalar stepFraction,
|
label& tetPtI,
|
||||||
DynamicList<label>& faceList
|
const edge& e
|
||||||
) const;
|
);
|
||||||
|
|
||||||
|
//- Hit wall faces in the current cell if the
|
||||||
|
//- wallImpactDistance is non-zero. They may not be in
|
||||||
|
//- different tets to the current.
|
||||||
|
inline void hitWallFaces
|
||||||
|
(
|
||||||
|
const vector& from,
|
||||||
|
const vector& to,
|
||||||
|
scalar& lambdaMin,
|
||||||
|
tetIndices& closestTetIs
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// Patch interactions
|
// Patch interactions
|
||||||
|
|
||||||
//- Overridable function to handle the particle hitting a patch
|
//- Overridable function to handle the particle hitting a
|
||||||
// Executed before other patch-hitting functions
|
// patch. Executed before other patch-hitting functions.
|
||||||
|
// trackFraction is passed in to allow mesh motion to
|
||||||
|
// interpolate in time to the correct face state.
|
||||||
template<class TrackData>
|
template<class TrackData>
|
||||||
bool hitPatch
|
bool hitPatch
|
||||||
(
|
(
|
||||||
const polyPatch&,
|
const polyPatch&,
|
||||||
TrackData& td,
|
TrackData& td,
|
||||||
const label patchI
|
const label patchI,
|
||||||
|
const scalar trackFraction,
|
||||||
|
const tetIndices& tetIs
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Overridable function to handle the particle hitting a wedgePatch
|
//- Overridable function to handle the particle hitting a wedgePatch
|
||||||
@ -231,7 +272,8 @@ protected:
|
|||||||
void hitWallPatch
|
void hitWallPatch
|
||||||
(
|
(
|
||||||
const wallPolyPatch&,
|
const wallPolyPatch&,
|
||||||
TrackData& td
|
TrackData& td,
|
||||||
|
const tetIndices& tetIs
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Overridable function to handle the particle hitting a
|
//- Overridable function to handle the particle hitting a
|
||||||
@ -264,12 +306,12 @@ protected:
|
|||||||
//- Convert global addressing to the processor patch
|
//- Convert global addressing to the processor patch
|
||||||
// local equivalents
|
// local equivalents
|
||||||
template<class TrackData>
|
template<class TrackData>
|
||||||
void prepareForParallelTransfer(const label patchi, TrackData& td);
|
void prepareForParallelTransfer(const label patchI, TrackData& td);
|
||||||
|
|
||||||
//- Convert processor patch addressing to the global equivalents
|
//- Convert processor patch addressing to the global equivalents
|
||||||
// and set the celli to the face-neighbour
|
// and set the cellI to the face-neighbour
|
||||||
template<class TrackData>
|
template<class TrackData>
|
||||||
void correctAfterParallelTransfer(const label patchi, TrackData& td);
|
void correctAfterParallelTransfer(const label patchI, TrackData& td);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -293,7 +335,18 @@ public:
|
|||||||
(
|
(
|
||||||
const Cloud<ParticleType>&,
|
const Cloud<ParticleType>&,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label celli
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from components, tetFaceI_ and tetPtI_ are not
|
||||||
|
// supplied so they will be deduced by a search
|
||||||
|
Particle
|
||||||
|
(
|
||||||
|
const Cloud<ParticleType>&,
|
||||||
|
const vector& position,
|
||||||
|
const label cellI
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Construct from Istream
|
//- Construct from Istream
|
||||||
@ -355,17 +408,6 @@ public:
|
|||||||
|
|
||||||
// Access
|
// Access
|
||||||
|
|
||||||
//- Return true if particle is in cell
|
|
||||||
inline bool inCell() const;
|
|
||||||
|
|
||||||
//- Return true if position is in cell i
|
|
||||||
inline bool inCell
|
|
||||||
(
|
|
||||||
const vector& position,
|
|
||||||
const label celli,
|
|
||||||
const scalar stepFraction
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Return current particle position
|
//- Return current particle position
|
||||||
inline const vector& position() const;
|
inline const vector& position() const;
|
||||||
|
|
||||||
@ -378,6 +420,35 @@ public:
|
|||||||
//- Return current cell particle is in
|
//- Return current cell particle is in
|
||||||
inline label cell() const;
|
inline label cell() const;
|
||||||
|
|
||||||
|
//- Return current tet face particle is in
|
||||||
|
inline label& tetFace();
|
||||||
|
|
||||||
|
//- Return current tet face particle is in
|
||||||
|
inline label tetFace() const;
|
||||||
|
|
||||||
|
//- Return current tet face particle is in
|
||||||
|
inline label& tetPt();
|
||||||
|
|
||||||
|
//- Return current tet face particle is in
|
||||||
|
inline label tetPt() const;
|
||||||
|
|
||||||
|
//- Return the indices of the current tet that the
|
||||||
|
// particle occupies.
|
||||||
|
inline tetIndices currentTetIndices() const;
|
||||||
|
|
||||||
|
//- Return the geometry of the current tet that the
|
||||||
|
// particle occupies.
|
||||||
|
inline tetPointRef currentTet() const;
|
||||||
|
|
||||||
|
//- Return the normal of the tri on tetFaceI_ for the
|
||||||
|
// current tet.
|
||||||
|
inline vector normal() const;
|
||||||
|
|
||||||
|
//- Return the normal of the tri on tetFaceI_ for the
|
||||||
|
// current tet at the start of the timestep, i.e. based
|
||||||
|
// on oldPoints
|
||||||
|
inline vector oldNormal() const;
|
||||||
|
|
||||||
//- Return current face particle is on otherwise -1
|
//- Return current face particle is on otherwise -1
|
||||||
inline label& face();
|
inline label& face();
|
||||||
|
|
||||||
@ -396,17 +467,21 @@ public:
|
|||||||
|
|
||||||
// Check
|
// Check
|
||||||
|
|
||||||
|
//- Check the stored cell value (setting if necessary) and
|
||||||
|
// initialise the tetFace and tetPt values
|
||||||
|
inline void initCellFacePt();
|
||||||
|
|
||||||
//- Is the particle on the boundary/(or outside the domain)?
|
//- Is the particle on the boundary/(or outside the domain)?
|
||||||
inline bool onBoundary() const;
|
inline bool onBoundary() const;
|
||||||
|
|
||||||
//- Which patch is particle on
|
//- Which patch is particle on
|
||||||
inline label patch(const label facei) const;
|
inline label patch(const label faceI) const;
|
||||||
|
|
||||||
//- Which face of this patch is this particle on
|
//- Which face of this patch is this particle on
|
||||||
inline label patchFace
|
inline label patchFace
|
||||||
(
|
(
|
||||||
const label patchi,
|
const label patchI,
|
||||||
const label facei
|
const label faceI
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- The nearest distance to a wall that
|
//- The nearest distance to a wall that
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,8 @@ License
|
|||||||
|
|
||||||
template<class ParticleType>
|
template<class ParticleType>
|
||||||
Foam::string Foam::Particle<ParticleType>::propHeader =
|
Foam::string Foam::Particle<ParticleType>::propHeader =
|
||||||
"(Px Py Pz) cellI origProc origId";
|
"(Px Py Pz) cellI tetFaceI tetPtI origProc origId";
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -44,20 +45,24 @@ Foam::Particle<ParticleType>::Particle
|
|||||||
)
|
)
|
||||||
:
|
:
|
||||||
cloud_(cloud),
|
cloud_(cloud),
|
||||||
facei_(-1),
|
position_(),
|
||||||
|
cellI_(-1),
|
||||||
|
faceI_(-1),
|
||||||
stepFraction_(0.0),
|
stepFraction_(0.0),
|
||||||
|
tetFaceI_(-1),
|
||||||
|
tetPtI_(-1),
|
||||||
origProc_(Pstream::myProcNo()),
|
origProc_(Pstream::myProcNo()),
|
||||||
origId_(-1)
|
origId_(-1)
|
||||||
{
|
{
|
||||||
|
|
||||||
// readFields : read additional data. Should be consistent with writeFields.
|
// readFields : read additional data. Should be consistent with writeFields.
|
||||||
|
|
||||||
if (is.format() == IOstream::ASCII)
|
if (is.format() == IOstream::ASCII)
|
||||||
{
|
{
|
||||||
is >> position_ >> celli_;
|
is >> position_ >> cellI_;
|
||||||
|
|
||||||
if (readFields)
|
if (readFields)
|
||||||
{
|
{
|
||||||
is >> origProc_ >> origId_;
|
is >> tetFaceI_ >> tetPtI_ >> origProc_ >> origId_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -69,9 +74,11 @@ Foam::Particle<ParticleType>::Particle
|
|||||||
(
|
(
|
||||||
reinterpret_cast<char*>(&position_),
|
reinterpret_cast<char*>(&position_),
|
||||||
sizeof(position_)
|
sizeof(position_)
|
||||||
+ sizeof(celli_)
|
+ sizeof(cellI_)
|
||||||
+ sizeof(facei_)
|
+ sizeof(faceI_)
|
||||||
+ sizeof(stepFraction_)
|
+ sizeof(stepFraction_)
|
||||||
|
+ sizeof(tetFaceI_)
|
||||||
|
+ sizeof(tetPtI_)
|
||||||
+ sizeof(origProc_)
|
+ sizeof(origProc_)
|
||||||
+ sizeof(origId_)
|
+ sizeof(origId_)
|
||||||
);
|
);
|
||||||
@ -82,18 +89,13 @@ Foam::Particle<ParticleType>::Particle
|
|||||||
(
|
(
|
||||||
reinterpret_cast<char*>(&position_),
|
reinterpret_cast<char*>(&position_),
|
||||||
sizeof(position_)
|
sizeof(position_)
|
||||||
+ sizeof(celli_)
|
+ sizeof(cellI_)
|
||||||
+ sizeof(facei_)
|
+ sizeof(faceI_)
|
||||||
+ sizeof(stepFraction_)
|
+ sizeof(stepFraction_)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (celli_ == -1)
|
|
||||||
{
|
|
||||||
celli_ = cloud_.pMesh().findCell(position_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check state of Istream
|
// Check state of Istream
|
||||||
is.check("Particle<ParticleType>::Particle(Istream&)");
|
is.check("Particle<ParticleType>::Particle(Istream&)");
|
||||||
}
|
}
|
||||||
@ -177,28 +179,32 @@ void Foam::Particle<ParticleType>::write(Ostream& os, bool writeFields) const
|
|||||||
{
|
{
|
||||||
// Write the additional entries
|
// Write the additional entries
|
||||||
os << position_
|
os << position_
|
||||||
<< token::SPACE << celli_
|
<< token::SPACE << cellI_
|
||||||
|
<< token::SPACE << tetFaceI_
|
||||||
|
<< token::SPACE << tetPtI_
|
||||||
<< token::SPACE << origProc_
|
<< token::SPACE << origProc_
|
||||||
<< token::SPACE << origId_;
|
<< token::SPACE << origId_;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
os << position_
|
os << position_
|
||||||
<< token::SPACE << celli_;
|
<< token::SPACE << cellI_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// In binary write both celli_ and facei_, needed for parallel transfer
|
// In binary write both cellI_ and faceI_, needed for parallel transfer
|
||||||
if (writeFields)
|
if (writeFields)
|
||||||
{
|
{
|
||||||
os.write
|
os.write
|
||||||
(
|
(
|
||||||
reinterpret_cast<const char*>(&position_),
|
reinterpret_cast<const char*>(&position_),
|
||||||
sizeof(position_)
|
sizeof(position_)
|
||||||
+ sizeof(celli_)
|
+ sizeof(cellI_)
|
||||||
+ sizeof(facei_)
|
+ sizeof(faceI_)
|
||||||
+ sizeof(stepFraction_)
|
+ sizeof(stepFraction_)
|
||||||
|
+ sizeof(tetFaceI_)
|
||||||
|
+ sizeof(tetPtI_)
|
||||||
+ sizeof(origProc_)
|
+ sizeof(origProc_)
|
||||||
+ sizeof(origId_)
|
+ sizeof(origId_)
|
||||||
);
|
);
|
||||||
@ -209,8 +215,8 @@ void Foam::Particle<ParticleType>::write(Ostream& os, bool writeFields) const
|
|||||||
(
|
(
|
||||||
reinterpret_cast<const char*>(&position_),
|
reinterpret_cast<const char*>(&position_),
|
||||||
sizeof(position_)
|
sizeof(position_)
|
||||||
+ sizeof(celli_)
|
+ sizeof(cellI_)
|
||||||
+ sizeof(facei_)
|
+ sizeof(faceI_)
|
||||||
+ sizeof(stepFraction_)
|
+ sizeof(stepFraction_)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,11 +67,26 @@ public:
|
|||||||
(
|
(
|
||||||
const Cloud<indexedParticle>& c,
|
const Cloud<indexedParticle>& c,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label celli,
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI,
|
||||||
const label index = 0
|
const label index = 0
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
Particle<indexedParticle>(c, position, celli),
|
Particle<indexedParticle>(c, position, cellI, tetFaceI, tetPtI),
|
||||||
|
index_(index)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Construct from components, with searching for tetFace and tetPt
|
||||||
|
indexedParticle
|
||||||
|
(
|
||||||
|
const Cloud<indexedParticle>& c,
|
||||||
|
const vector& position,
|
||||||
|
const label cellI,
|
||||||
|
const label index = 0
|
||||||
|
)
|
||||||
|
:
|
||||||
|
Particle<indexedParticle>(c, position, cellI),
|
||||||
index_(index)
|
index_(index)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|||||||
@ -60,10 +60,23 @@ public:
|
|||||||
(
|
(
|
||||||
const Cloud<passiveParticle>& c,
|
const Cloud<passiveParticle>& c,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label celli
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
Particle<passiveParticle>(c, position, celli)
|
Particle<passiveParticle>(c, position, cellI, tetFaceI, tetPtI)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Construct from components, with searching for tetFace and tetPt
|
||||||
|
passiveParticle
|
||||||
|
(
|
||||||
|
const Cloud<passiveParticle>& c,
|
||||||
|
const vector& position,
|
||||||
|
const label cellI
|
||||||
|
)
|
||||||
|
:
|
||||||
|
Particle<passiveParticle>(c, position, cellI)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
//- Construct from Istream
|
//- Construct from Istream
|
||||||
|
|||||||
@ -31,10 +31,19 @@ Foam::coalParcel::coalParcel
|
|||||||
(
|
(
|
||||||
ReactingMultiphaseCloud<coalParcel>& owner,
|
ReactingMultiphaseCloud<coalParcel>& owner,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label cellI
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
ReactingMultiphaseParcel<coalParcel>(owner, position, cellI)
|
ReactingMultiphaseParcel<coalParcel>
|
||||||
|
(
|
||||||
|
owner,
|
||||||
|
position,
|
||||||
|
cellI,
|
||||||
|
tetFaceI,
|
||||||
|
tetPtI
|
||||||
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
@ -43,6 +52,8 @@ Foam::coalParcel::coalParcel
|
|||||||
ReactingMultiphaseCloud<coalParcel>& owner,
|
ReactingMultiphaseCloud<coalParcel>& owner,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label cellI,
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI,
|
||||||
const label typeId,
|
const label typeId,
|
||||||
const scalar nParticle0,
|
const scalar nParticle0,
|
||||||
const scalar d0,
|
const scalar d0,
|
||||||
@ -62,6 +73,8 @@ Foam::coalParcel::coalParcel
|
|||||||
owner,
|
owner,
|
||||||
position,
|
position,
|
||||||
cellI,
|
cellI,
|
||||||
|
tetFaceI,
|
||||||
|
tetPtI,
|
||||||
typeId,
|
typeId,
|
||||||
nParticle0,
|
nParticle0,
|
||||||
d0,
|
d0,
|
||||||
|
|||||||
@ -63,7 +63,9 @@ public:
|
|||||||
(
|
(
|
||||||
ReactingMultiphaseCloud<coalParcel>& owner,
|
ReactingMultiphaseCloud<coalParcel>& owner,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label cellI
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Construct from components
|
//- Construct from components
|
||||||
@ -72,6 +74,8 @@ public:
|
|||||||
ReactingMultiphaseCloud<coalParcel>& owner,
|
ReactingMultiphaseCloud<coalParcel>& owner,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label cellI,
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI,
|
||||||
const label typeId,
|
const label typeId,
|
||||||
const scalar nParticle0,
|
const scalar nParticle0,
|
||||||
const scalar d0,
|
const scalar d0,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||||
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
|
||||||
-I$(LIB_SRC)/turbulenceModels \
|
-I$(LIB_SRC)/turbulenceModels \
|
||||||
-I$(LIB_SRC)/turbulenceModels/compressible/turbulenceModel \
|
-I$(LIB_SRC)/turbulenceModels/compressible/turbulenceModel \
|
||||||
@ -16,6 +17,7 @@ EXE_INC = \
|
|||||||
|
|
||||||
LIB_LIBS = \
|
LIB_LIBS = \
|
||||||
-llagrangian \
|
-llagrangian \
|
||||||
|
-lmeshTools \
|
||||||
-lfiniteVolume \
|
-lfiniteVolume \
|
||||||
-lcompressibleRASModels \
|
-lcompressibleRASModels \
|
||||||
-lcompressibleLESModels \
|
-lcompressibleLESModels \
|
||||||
|
|||||||
@ -15,12 +15,11 @@ if (isA<wallPolyPatch>(pbMesh[patch(face())]))
|
|||||||
else if (isA<wedgePolyPatch>(pbMesh[patch(face())]))
|
else if (isA<wedgePolyPatch>(pbMesh[patch(face())]))
|
||||||
{
|
{
|
||||||
// check if parcel is trying to move out of the domain
|
// check if parcel is trying to move out of the domain
|
||||||
label patchi = patch(face());
|
|
||||||
label patchFacei = patchFace(patchi, face());
|
vector nf = normal();
|
||||||
const polyPatch& patch = mesh.boundaryMesh()[patchi];
|
|
||||||
vector nf = patch.faceAreas()[patchFacei];
|
|
||||||
|
|
||||||
scalar Un = U() & nf;
|
scalar Un = U() & nf;
|
||||||
|
|
||||||
if (Un > 0)
|
if (Un > 0)
|
||||||
{
|
{
|
||||||
scalar Un2 = U() & n();
|
scalar Un2 = U() & n();
|
||||||
@ -30,12 +29,11 @@ else if (isA<wedgePolyPatch>(pbMesh[patch(face())]))
|
|||||||
else if (isA<symmetryPolyPatch>(pbMesh[patch(face())]))
|
else if (isA<symmetryPolyPatch>(pbMesh[patch(face())]))
|
||||||
{
|
{
|
||||||
// check if parcel is trying to move out of the domain
|
// check if parcel is trying to move out of the domain
|
||||||
label patchi = patch(face());
|
|
||||||
label patchFacei = patchFace(patchi, face());
|
vector nf = normal();
|
||||||
const polyPatch& patch = mesh.boundaryMesh()[patchi];
|
|
||||||
vector nf = patch.faceAreas()[patchFacei];
|
|
||||||
|
|
||||||
scalar Un = U() & nf;
|
scalar Un = U() & nf;
|
||||||
|
|
||||||
if (Un > 0)
|
if (Un > 0)
|
||||||
{
|
{
|
||||||
if (sDB.twoD())
|
if (sDB.twoD())
|
||||||
|
|||||||
@ -50,6 +50,8 @@ Foam::parcel::parcel
|
|||||||
const Cloud<parcel>& cloud,
|
const Cloud<parcel>& cloud,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label cellI,
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI,
|
||||||
const vector& n,
|
const vector& n,
|
||||||
const scalar d,
|
const scalar d,
|
||||||
const scalar T,
|
const scalar T,
|
||||||
@ -67,7 +69,7 @@ Foam::parcel::parcel
|
|||||||
const List<word>& liquidNames
|
const List<word>& liquidNames
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
Particle<parcel>(cloud, position, cellI),
|
Particle<parcel>(cloud, position, cellI, tetFaceI, tetPtI),
|
||||||
liquidComponents_
|
liquidComponents_
|
||||||
(
|
(
|
||||||
liquidNames
|
liquidNames
|
||||||
@ -103,12 +105,13 @@ bool Foam::parcel::move(spray& sDB)
|
|||||||
label Nf = fuels.components().size();
|
label Nf = fuels.components().size();
|
||||||
label Ns = sDB.composition().Y().size();
|
label Ns = sDB.composition().Y().size();
|
||||||
|
|
||||||
|
tetIndices tetIs = this->currentTetIndices();
|
||||||
|
|
||||||
// Calculate the interpolated gas properties at the position of the parcel
|
// Calculate the interpolated gas properties at the position of the parcel
|
||||||
vector Up = sDB.UInterpolator().interpolate(position(), cell())
|
vector Up = sDB.UInterpolator().interpolate(position(), tetIs) + Uturb();
|
||||||
+ Uturb();
|
scalar rhog = sDB.rhoInterpolator().interpolate(position(), tetIs);
|
||||||
scalar rhog = sDB.rhoInterpolator().interpolate(position(), cell());
|
scalar pg = sDB.pInterpolator().interpolate(position(), tetIs);
|
||||||
scalar pg = sDB.pInterpolator().interpolate(position(), cell());
|
scalar Tg = sDB.TInterpolator().interpolate(position(), tetIs);
|
||||||
scalar Tg = sDB.TInterpolator().interpolate(position(), cell());
|
|
||||||
|
|
||||||
scalarField Yfg(Nf, 0.0);
|
scalarField Yfg(Nf, 0.0);
|
||||||
|
|
||||||
@ -119,8 +122,8 @@ bool Foam::parcel::move(spray& sDB)
|
|||||||
if (sDB.isLiquidFuel()[i])
|
if (sDB.isLiquidFuel()[i])
|
||||||
{
|
{
|
||||||
label j = sDB.gasToLiquidIndex()[i];
|
label j = sDB.gasToLiquidIndex()[i];
|
||||||
scalar Yicelli = Yi[cell()];
|
scalar YicellI = Yi[cell()];
|
||||||
Yfg[j] = Yicelli;
|
Yfg[j] = YicellI;
|
||||||
}
|
}
|
||||||
cpMixture += Yi[cell()]*sDB.gasProperties()[i].Cp(Tg);
|
cpMixture += Yi[cell()]*sDB.gasProperties()[i].Cp(Tg);
|
||||||
}
|
}
|
||||||
@ -199,8 +202,8 @@ bool Foam::parcel::move(spray& sDB)
|
|||||||
|
|
||||||
// remember which cell the parcel is in
|
// remember which cell the parcel is in
|
||||||
// since this will change if a face is hit
|
// since this will change if a face is hit
|
||||||
label celli = cell();
|
label cellI = cell();
|
||||||
scalar p = sDB.p()[celli];
|
scalar p = sDB.p()[cellI];
|
||||||
|
|
||||||
// track parcel to face, or end of trajectory
|
// track parcel to face, or end of trajectory
|
||||||
if (keepParcel)
|
if (keepParcel)
|
||||||
@ -259,7 +262,7 @@ bool Foam::parcel::move(spray& sDB)
|
|||||||
(
|
(
|
||||||
dt,
|
dt,
|
||||||
sDB,
|
sDB,
|
||||||
celli,
|
cellI,
|
||||||
face()
|
face()
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -283,11 +286,11 @@ bool Foam::parcel::move(spray& sDB)
|
|||||||
// Update the Spray Source Terms
|
// Update the Spray Source Terms
|
||||||
forAll(nMass, i)
|
forAll(nMass, i)
|
||||||
{
|
{
|
||||||
sDB.srhos()[i][celli] += oMass[i] - nMass[i];
|
sDB.srhos()[i][cellI] += oMass[i] - nMass[i];
|
||||||
}
|
}
|
||||||
sDB.sms()[celli] += oMom - nMom;
|
sDB.sms()[cellI] += oMom - nMom;
|
||||||
|
|
||||||
sDB.shs()[celli] += oTotMass*(oH + oPE) - m()*(nH + nPE);
|
sDB.shs()[cellI] += oTotMass*(oH + oPE) - m()*(nH + nPE);
|
||||||
|
|
||||||
// Remove evaporated mass from stripped mass
|
// Remove evaporated mass from stripped mass
|
||||||
ms() -= ms()*(oTotMass-m())/oTotMass;
|
ms() -= ms()*(oTotMass-m())/oTotMass;
|
||||||
@ -300,11 +303,11 @@ bool Foam::parcel::move(spray& sDB)
|
|||||||
// ... and add the removed 'stuff' to the gas
|
// ... and add the removed 'stuff' to the gas
|
||||||
forAll(nMass, i)
|
forAll(nMass, i)
|
||||||
{
|
{
|
||||||
sDB.srhos()[i][celli] += nMass[i];
|
sDB.srhos()[i][cellI] += nMass[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
sDB.sms()[celli] += nMom;
|
sDB.sms()[cellI] += nMom;
|
||||||
sDB.shs()[celli] += m()*(nH + nPE);
|
sDB.shs()[cellI] += m()*(nH + nPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onBoundary() && keepParcel)
|
if (onBoundary() && keepParcel)
|
||||||
@ -327,8 +330,8 @@ void Foam::parcel::updateParcelProperties
|
|||||||
(
|
(
|
||||||
const scalar dt,
|
const scalar dt,
|
||||||
spray& sDB,
|
spray& sDB,
|
||||||
const label celli,
|
const label cellI,
|
||||||
const label facei
|
const label faceI
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const liquidMixture& fuels = sDB.fuels();
|
const liquidMixture& fuels = sDB.fuels();
|
||||||
@ -340,34 +343,34 @@ void Foam::parcel::updateParcelProperties
|
|||||||
scalar W = 0.0;
|
scalar W = 0.0;
|
||||||
for (label i=0; i<Ns; i++)
|
for (label i=0; i<Ns; i++)
|
||||||
{
|
{
|
||||||
W += sDB.composition().Y()[i][celli]/sDB.gasProperties()[i].W();
|
W += sDB.composition().Y()[i][cellI]/sDB.gasProperties()[i].W();
|
||||||
|
|
||||||
}
|
}
|
||||||
W = 1.0/W;
|
W = 1.0/W;
|
||||||
|
|
||||||
// Calculate the interpolated gas properties at the position of the parcel
|
// Calculate the interpolated gas properties at the position of the parcel
|
||||||
vector Up = sDB.UInterpolator().interpolate(position(), celli, facei)
|
vector Up = sDB.UInterpolator().interpolate(position(), cellI, faceI)
|
||||||
+ Uturb();
|
+ Uturb();
|
||||||
scalar rhog = sDB.rhoInterpolator().interpolate(position(), celli, facei);
|
scalar rhog = sDB.rhoInterpolator().interpolate(position(), cellI, faceI);
|
||||||
scalar pg = sDB.pInterpolator().interpolate(position(), celli, facei);
|
scalar pg = sDB.pInterpolator().interpolate(position(), cellI, faceI);
|
||||||
scalar Tg0 = sDB.TInterpolator().interpolate(position(), celli, facei);
|
scalar Tg0 = sDB.TInterpolator().interpolate(position(), cellI, faceI);
|
||||||
|
|
||||||
// correct the gaseous temperature for evaporated fuel
|
// correct the gaseous temperature for evaporated fuel
|
||||||
scalar cpMix = 0.0;
|
scalar cpMix = 0.0;
|
||||||
for (label i=0; i<Ns; i++)
|
for (label i=0; i<Ns; i++)
|
||||||
{
|
{
|
||||||
cpMix += sDB.composition().Y()[i][celli]
|
cpMix += sDB.composition().Y()[i][cellI]
|
||||||
*sDB.gasProperties()[i].Cp(T());
|
*sDB.gasProperties()[i].Cp(T());
|
||||||
}
|
}
|
||||||
scalar cellV = sDB.mesh().V()[celli];
|
scalar cellV = sDB.mesh().V()[cellI];
|
||||||
scalar rho = sDB.rho()[celli];
|
scalar rho = sDB.rho()[cellI];
|
||||||
scalar cellMass = rho*cellV;
|
scalar cellMass = rho*cellV;
|
||||||
scalar dh = sDB.shs()[celli];
|
scalar dh = sDB.shs()[cellI];
|
||||||
scalarField addedMass(Nf, 0.0);
|
scalarField addedMass(Nf, 0.0);
|
||||||
|
|
||||||
forAll(addedMass, i)
|
forAll(addedMass, i)
|
||||||
{
|
{
|
||||||
addedMass[i] += sDB.srhos()[i][celli]*cellV;
|
addedMass[i] += sDB.srhos()[i][cellI]*cellV;
|
||||||
}
|
}
|
||||||
|
|
||||||
scalar Tg = Tg0 + dh/(cpMix*cellMass);
|
scalar Tg = Tg0 + dh/(cpMix*cellMass);
|
||||||
@ -378,7 +381,7 @@ void Foam::parcel::updateParcelProperties
|
|||||||
{
|
{
|
||||||
label j = sDB.liquidToGasIndex()[i];
|
label j = sDB.liquidToGasIndex()[i];
|
||||||
const volScalarField& Yj = sDB.composition().Y()[j];
|
const volScalarField& Yj = sDB.composition().Y()[j];
|
||||||
scalar Yfg0 = Yj[celli];
|
scalar Yfg0 = Yj[cellI];
|
||||||
Yfg[i] = (Yfg0*cellMass + addedMass[i])/(addedMass[i] + cellMass);
|
Yfg[i] = (Yfg0*cellMass + addedMass[i])/(addedMass[i] + cellMass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,7 +392,7 @@ void Foam::parcel::updateParcelProperties
|
|||||||
|
|
||||||
setRelaxationTimes
|
setRelaxationTimes
|
||||||
(
|
(
|
||||||
celli,
|
cellI,
|
||||||
tauMomentum,
|
tauMomentum,
|
||||||
tauEvaporation,
|
tauEvaporation,
|
||||||
tauHeatTransfer,
|
tauHeatTransfer,
|
||||||
@ -492,14 +495,14 @@ void Foam::parcel::updateParcelProperties
|
|||||||
{
|
{
|
||||||
label j = sDB.liquidToGasIndex()[i];
|
label j = sDB.liquidToGasIndex()[i];
|
||||||
const volScalarField& Yj = sDB.composition().Y()[j];
|
const volScalarField& Yj = sDB.composition().Y()[j];
|
||||||
scalar Yfg0 = Yj[celli];
|
scalar Yfg0 = Yj[cellI];
|
||||||
Yfg[i] = (Yfg0*cellMass + addedMass[i] + dm)
|
Yfg[i] = (Yfg0*cellMass + addedMass[i] + dm)
|
||||||
/(addedMass[i] + cellMass + dm);
|
/(addedMass[i] + cellMass + dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
setRelaxationTimes
|
setRelaxationTimes
|
||||||
(
|
(
|
||||||
celli,
|
cellI,
|
||||||
tauMomentum,
|
tauMomentum,
|
||||||
tauEvaporation,
|
tauEvaporation,
|
||||||
tauHeatTransfer,
|
tauHeatTransfer,
|
||||||
@ -530,7 +533,7 @@ void Foam::parcel::updateParcelProperties
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
scalar Y = sDB.composition().Y()[i][celli];
|
scalar Y = sDB.composition().Y()[i][cellI];
|
||||||
cpMix += Y*sDB.gasProperties()[i].Cp(Taverage);
|
cpMix += Y*sDB.gasProperties()[i].Cp(Taverage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -113,7 +113,7 @@ class parcel
|
|||||||
//- Set the relaxation times
|
//- Set the relaxation times
|
||||||
void setRelaxationTimes
|
void setRelaxationTimes
|
||||||
(
|
(
|
||||||
label celli,
|
label cellI,
|
||||||
scalar& tauMomentum,
|
scalar& tauMomentum,
|
||||||
scalarField& tauEvaporation,
|
scalarField& tauEvaporation,
|
||||||
scalar& tauHeatTransfer,
|
scalar& tauHeatTransfer,
|
||||||
@ -133,8 +133,8 @@ class parcel
|
|||||||
(
|
(
|
||||||
const scalar dt,
|
const scalar dt,
|
||||||
spray& sprayData,
|
spray& sprayData,
|
||||||
const label celli,
|
const label cellI,
|
||||||
const label facei
|
const label faceI
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -150,7 +150,9 @@ public:
|
|||||||
(
|
(
|
||||||
const Cloud<parcel>& cloud,
|
const Cloud<parcel>& cloud,
|
||||||
const vector& position,
|
const vector& position,
|
||||||
const label celli,
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI,
|
||||||
const vector& n,
|
const vector& n,
|
||||||
const scalar d,
|
const scalar d,
|
||||||
const scalar T,
|
const scalar T,
|
||||||
|
|||||||
@ -36,7 +36,7 @@ License
|
|||||||
|
|
||||||
void Foam::parcel::setRelaxationTimes
|
void Foam::parcel::setRelaxationTimes
|
||||||
(
|
(
|
||||||
label celli,
|
label cellI,
|
||||||
scalar& tauMomentum,
|
scalar& tauMomentum,
|
||||||
scalarField& tauEvaporation,
|
scalarField& tauEvaporation,
|
||||||
scalar& tauHeatTransfer,
|
scalar& tauHeatTransfer,
|
||||||
@ -70,7 +70,7 @@ void Foam::parcel::setRelaxationTimes
|
|||||||
|
|
||||||
for (label i=0; i<Ns; i++)
|
for (label i=0; i<Ns; i++)
|
||||||
{
|
{
|
||||||
scalar Y = sDB.composition().Y()[i][celli];
|
scalar Y = sDB.composition().Y()[i][cellI];
|
||||||
W += Y/sDB.gasProperties()[i].W();
|
W += Y/sDB.gasProperties()[i].W();
|
||||||
// Using mass-fractions to average...
|
// Using mass-fractions to average...
|
||||||
kMixture += Y*sDB.gasProperties()[i].kappa(Tf);
|
kMixture += Y*sDB.gasProperties()[i].kappa(Tf);
|
||||||
@ -87,7 +87,7 @@ void Foam::parcel::setRelaxationTimes
|
|||||||
for (label i=0; i<Nf; i++)
|
for (label i=0; i<Nf; i++)
|
||||||
{
|
{
|
||||||
label j = sDB.liquidToGasIndex()[i];
|
label j = sDB.liquidToGasIndex()[i];
|
||||||
scalar Y = sDB.composition().Y()[j][celli];
|
scalar Y = sDB.composition().Y()[j][cellI];
|
||||||
scalar Wi = sDB.gasProperties()[j].W();
|
scalar Wi = sDB.gasProperties()[j].W();
|
||||||
Yf[i] = Y;
|
Yf[i] = Y;
|
||||||
Xf[i] = Y*W/Wi;
|
Xf[i] = Y*W/Wi;
|
||||||
@ -264,10 +264,10 @@ void Foam::parcel::setRelaxationTimes
|
|||||||
forAll(sDB.gasProperties(), k)
|
forAll(sDB.gasProperties(), k)
|
||||||
{
|
{
|
||||||
vapourSurfaceEnthalpy +=
|
vapourSurfaceEnthalpy +=
|
||||||
sDB.composition().Y()[k][celli]
|
sDB.composition().Y()[k][cellI]
|
||||||
*sDB.gasProperties()[k].H(tBoilingSurface);
|
*sDB.gasProperties()[k].H(tBoilingSurface);
|
||||||
vapourFarEnthalpy +=
|
vapourFarEnthalpy +=
|
||||||
sDB.composition().Y()[k][celli]
|
sDB.composition().Y()[k][cellI]
|
||||||
*sDB.gasProperties()[k].H(temperature);
|
*sDB.gasProperties()[k].H(temperature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,14 @@ reduce(foundCell, orOp<bool>());
|
|||||||
if (!foundCell)
|
if (!foundCell)
|
||||||
{
|
{
|
||||||
injectionPosition = it->position(n);
|
injectionPosition = it->position(n);
|
||||||
injectorCell = mesh_.findCell(injectionPosition);
|
|
||||||
|
findCellFacePt
|
||||||
|
(
|
||||||
|
injectionPosition,
|
||||||
|
injectorCell,
|
||||||
|
injectorTetFaceI,
|
||||||
|
injectorTetPtI
|
||||||
|
);
|
||||||
|
|
||||||
if (injectorCell >= 0)
|
if (injectorCell >= 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -241,16 +241,16 @@ Foam::spray::spray
|
|||||||
label n=0;
|
label n=0;
|
||||||
|
|
||||||
// check for the type of boundary condition
|
// check for the type of boundary condition
|
||||||
forAll(bMesh, patchi)
|
forAll(bMesh, patchI)
|
||||||
{
|
{
|
||||||
if (isA<symmetryPolyPatch>(bMesh[patchi]))
|
if (isA<symmetryPolyPatch>(bMesh[patchI]))
|
||||||
{
|
{
|
||||||
symPlaneExist = true;
|
symPlaneExist = true;
|
||||||
}
|
}
|
||||||
else if (isA<wedgePolyPatch>(bMesh[patchi]))
|
else if (isA<wedgePolyPatch>(bMesh[patchI]))
|
||||||
{
|
{
|
||||||
wedgeExist = true;
|
wedgeExist = true;
|
||||||
patches[n++] = patchi;
|
patches[n++] = patchI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -149,9 +149,9 @@ Foam::scalar Foam::spray::liquidTotalEnthalpy() const
|
|||||||
|
|
||||||
forAllConstIter(spray, *this, iter)
|
forAllConstIter(spray, *this, iter)
|
||||||
{
|
{
|
||||||
label celli = iter().cell();
|
label cellI = iter().cell();
|
||||||
scalar T = iter().T();
|
scalar T = iter().T();
|
||||||
scalar pc = p()[celli];
|
scalar pc = p()[cellI];
|
||||||
scalar rho = fuels().rho(pc, T, iter().X());
|
scalar rho = fuels().rho(pc, T, iter().X());
|
||||||
scalar hlat = fuels().hl(pc, T, iter().X());
|
scalar hlat = fuels().hl(pc, T, iter().X());
|
||||||
scalar hg = 0.0;
|
scalar hg = 0.0;
|
||||||
@ -351,8 +351,8 @@ Foam::scalar Foam::spray::smd() const
|
|||||||
|
|
||||||
forAllConstIter(spray, *this, iter)
|
forAllConstIter(spray, *this, iter)
|
||||||
{
|
{
|
||||||
label celli = iter().cell();
|
label cellI = iter().cell();
|
||||||
scalar Pc = p()[celli];
|
scalar Pc = p()[cellI];
|
||||||
scalar T = iter().T();
|
scalar T = iter().T();
|
||||||
scalar rho = fuels_->rho(Pc, T, iter().X());
|
scalar rho = fuels_->rho(Pc, T, iter().X());
|
||||||
|
|
||||||
|
|||||||
@ -107,7 +107,17 @@ void Foam::spray::inject()
|
|||||||
scalar deviation = breakup().y0();
|
scalar deviation = breakup().y0();
|
||||||
scalar ddev = breakup().yDot0();
|
scalar ddev = breakup().yDot0();
|
||||||
|
|
||||||
label injectorCell = mesh_.findCell(injectionPosition);
|
label injectorCell = -1;
|
||||||
|
label injectorTetFaceI = -1;
|
||||||
|
label injectorTetPtI = -1;
|
||||||
|
|
||||||
|
findCellFacePt
|
||||||
|
(
|
||||||
|
injectionPosition,
|
||||||
|
injectorCell,
|
||||||
|
injectorTetFaceI,
|
||||||
|
injectorTetPtI
|
||||||
|
);
|
||||||
|
|
||||||
# include "findInjectorCell.H"
|
# include "findInjectorCell.H"
|
||||||
|
|
||||||
@ -122,6 +132,8 @@ void Foam::spray::inject()
|
|||||||
*this,
|
*this,
|
||||||
injectionPosition,
|
injectionPosition,
|
||||||
injectorCell,
|
injectorCell,
|
||||||
|
injectorTetFaceI,
|
||||||
|
injectorTetPtI,
|
||||||
normal,
|
normal,
|
||||||
diameter,
|
diameter,
|
||||||
it->T(toi),
|
it->T(toi),
|
||||||
|
|||||||
@ -88,7 +88,7 @@ void Foam::spray::breakupLoop()
|
|||||||
vector velocity = UInterpolator().interpolate
|
vector velocity = UInterpolator().interpolate
|
||||||
(
|
(
|
||||||
elmnt().position(),
|
elmnt().position(),
|
||||||
elmnt().cell()
|
elmnt().currentTetIndices()
|
||||||
);
|
);
|
||||||
|
|
||||||
// liquidCore < 0.5 indicates discrete drops
|
// liquidCore < 0.5 indicates discrete drops
|
||||||
@ -122,7 +122,7 @@ void Foam::spray::atomizationLoop()
|
|||||||
vector velocity = UInterpolator().interpolate
|
vector velocity = UInterpolator().interpolate
|
||||||
(
|
(
|
||||||
elmnt().position(),
|
elmnt().position(),
|
||||||
elmnt().cell()
|
elmnt().currentTetIndices()
|
||||||
);
|
);
|
||||||
|
|
||||||
// liquidCore > 0.5 indicates a liquid core
|
// liquidCore > 0.5 indicates a liquid core
|
||||||
|
|||||||
@ -102,14 +102,14 @@ void Foam::SHF::breakupParcel
|
|||||||
const liquidMixture& fuels
|
const liquidMixture& fuels
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
label celli = p.cell();
|
label cellI = p.cell();
|
||||||
scalar T = p.T();
|
scalar T = p.T();
|
||||||
scalar pc = spray_.p()[celli];
|
scalar pc = spray_.p()[cellI];
|
||||||
|
|
||||||
scalar sigma = fuels.sigma(pc, T, p.X());
|
scalar sigma = fuels.sigma(pc, T, p.X());
|
||||||
scalar rhoLiquid = fuels.rho(pc, T, p.X());
|
scalar rhoLiquid = fuels.rho(pc, T, p.X());
|
||||||
scalar muLiquid = fuels.mu(pc, T, p.X());
|
scalar muLiquid = fuels.mu(pc, T, p.X());
|
||||||
scalar rhoGas = spray_.rho()[celli];
|
scalar rhoGas = spray_.rho()[cellI];
|
||||||
|
|
||||||
scalar weGas = p.We(vel, rhoGas, sigma);
|
scalar weGas = p.We(vel, rhoGas, sigma);
|
||||||
scalar weLiquid = p.We(vel, rhoLiquid, sigma);
|
scalar weLiquid = p.We(vel, rhoLiquid, sigma);
|
||||||
@ -237,6 +237,8 @@ void Foam::SHF::breakupParcel
|
|||||||
spray_,
|
spray_,
|
||||||
p.position(),
|
p.position(),
|
||||||
p.cell(),
|
p.cell(),
|
||||||
|
p.tetFace(),
|
||||||
|
p.tetPt(),
|
||||||
p.n(),
|
p.n(),
|
||||||
d,
|
d,
|
||||||
p.T(),
|
p.T(),
|
||||||
|
|||||||
@ -78,15 +78,15 @@ void Foam::reitzKHRT::breakupParcel
|
|||||||
const liquidMixture& fuels
|
const liquidMixture& fuels
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
label celli = p.cell();
|
label cellI = p.cell();
|
||||||
scalar T = p.T();
|
scalar T = p.T();
|
||||||
scalar r = 0.5*p.d();
|
scalar r = 0.5*p.d();
|
||||||
scalar pc = spray_.p()[celli];
|
scalar pc = spray_.p()[cellI];
|
||||||
|
|
||||||
scalar sigma = fuels.sigma(pc, T, p.X());
|
scalar sigma = fuels.sigma(pc, T, p.X());
|
||||||
scalar rhoLiquid = fuels.rho(pc, T, p.X());
|
scalar rhoLiquid = fuels.rho(pc, T, p.X());
|
||||||
scalar muLiquid = fuels.mu(pc, T, p.X());
|
scalar muLiquid = fuels.mu(pc, T, p.X());
|
||||||
scalar rhoGas = spray_.rho()[celli];
|
scalar rhoGas = spray_.rho()[cellI];
|
||||||
scalar Np = p.N(rhoLiquid);
|
scalar Np = p.N(rhoLiquid);
|
||||||
scalar semiMass = Np*pow3(p.d());
|
scalar semiMass = Np*pow3(p.d());
|
||||||
|
|
||||||
@ -198,6 +198,8 @@ void Foam::reitzKHRT::breakupParcel
|
|||||||
spray_,
|
spray_,
|
||||||
p.position(),
|
p.position(),
|
||||||
p.cell(),
|
p.cell(),
|
||||||
|
p.tetFace(),
|
||||||
|
p.tetPt(),
|
||||||
p.n(),
|
p.n(),
|
||||||
dc,
|
dc,
|
||||||
p.T(),
|
p.T(),
|
||||||
|
|||||||
@ -70,18 +70,18 @@ Foam::reflectParcel::~reflectParcel()
|
|||||||
bool Foam::reflectParcel::wallTreatment
|
bool Foam::reflectParcel::wallTreatment
|
||||||
(
|
(
|
||||||
parcel& p,
|
parcel& p,
|
||||||
const label globalFacei
|
const label globalFaceI
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
label patchi = p.patch(globalFacei);
|
label patchI = p.patch(globalFaceI);
|
||||||
label facei = p.patchFace(patchi, globalFacei);
|
label faceI = p.patchFace(patchI, globalFaceI);
|
||||||
|
|
||||||
const polyMesh& mesh = spray_.mesh();
|
const polyMesh& mesh = spray_.mesh();
|
||||||
|
|
||||||
if (isA<wallPolyPatch>(mesh_.boundaryMesh()[patchi]))
|
if (isA<wallPolyPatch>(mesh_.boundaryMesh()[patchI]))
|
||||||
{
|
{
|
||||||
// wallNormal defined to point outwards of domain
|
// wallNormal defined to point outwards of domain
|
||||||
vector Sf = mesh_.Sf().boundaryField()[patchi][facei];
|
vector Sf = mesh_.Sf().boundaryField()[patchI][faceI];
|
||||||
Sf /= mag(Sf);
|
Sf /= mag(Sf);
|
||||||
|
|
||||||
if (!mesh.moving())
|
if (!mesh.moving())
|
||||||
@ -97,17 +97,17 @@ bool Foam::reflectParcel::wallTreatment
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// moving mesh
|
// moving mesh
|
||||||
vector Ub1 = U_.boundaryField()[patchi][facei];
|
vector Ub1 = U_.boundaryField()[patchI][faceI];
|
||||||
vector Ub0 = U_.oldTime().boundaryField()[patchi][facei];
|
vector Ub0 = U_.oldTime().boundaryField()[patchI][faceI];
|
||||||
|
|
||||||
scalar dt = spray_.runTime().deltaTValue();
|
scalar dt = spray_.runTime().deltaTValue();
|
||||||
const vectorField& oldPoints = mesh.oldPoints();
|
const vectorField& oldPoints = mesh.oldPoints();
|
||||||
|
|
||||||
const vector& Cf1 = mesh.faceCentres()[globalFacei];
|
const vector& Cf1 = mesh.faceCentres()[globalFaceI];
|
||||||
|
|
||||||
vector Cf0 = mesh.faces()[globalFacei].centre(oldPoints);
|
vector Cf0 = mesh.faces()[globalFaceI].centre(oldPoints);
|
||||||
vector Cf = Cf0 + p.stepFraction()*(Cf1 - Cf0);
|
vector Cf = Cf0 + p.stepFraction()*(Cf1 - Cf0);
|
||||||
vector Sf0 = mesh.faces()[globalFacei].normal(oldPoints);
|
vector Sf0 = mesh.faces()[globalFaceI].normal(oldPoints);
|
||||||
|
|
||||||
// for layer addition Sf0 = vector::zero and we use Sf
|
// for layer addition Sf0 = vector::zero and we use Sf
|
||||||
if (mag(Sf0) > SMALL)
|
if (mag(Sf0) > SMALL)
|
||||||
@ -157,10 +157,10 @@ bool Foam::reflectParcel::wallTreatment
|
|||||||
{
|
{
|
||||||
Info<< "reflectParcel:: v = " << v
|
Info<< "reflectParcel:: v = " << v
|
||||||
<< ", Ub = " << Ub
|
<< ", Ub = " << Ub
|
||||||
<< ", facei = " << facei
|
<< ", faceI = " << faceI
|
||||||
<< ", patchi = " << patchi
|
<< ", patchI = " << patchI
|
||||||
<< ", globalFacei = " << globalFacei
|
<< ", globalFaceI = " << globalFaceI
|
||||||
<< ", name = " << mesh_.boundaryMesh()[patchi].name()
|
<< ", name = " << mesh_.boundaryMesh()[patchI].name()
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@ -175,7 +175,7 @@ bool Foam::reflectParcel::wallTreatment
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
FatalErrorIn("bool reflectParcel::wallTreatment(parcel& parcel) const")
|
FatalErrorIn("bool reflectParcel::wallTreatment(parcel& parcel) const")
|
||||||
<< " parcel has hit a boundary " << mesh_.boundary()[patchi].type()
|
<< " parcel has hit a boundary " << mesh_.boundary()[patchI].type()
|
||||||
<< " which not yet has been implemented." << nl
|
<< " which not yet has been implemented." << nl
|
||||||
<< abort(FatalError);
|
<< abort(FatalError);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,7 +87,7 @@ public:
|
|||||||
|
|
||||||
//- Return true if parcel is to be kept, and false if it is to be
|
//- Return true if parcel is to be kept, and false if it is to be
|
||||||
// removed
|
// removed
|
||||||
bool wallTreatment(parcel& parcel, const label facei) const;
|
bool wallTreatment(parcel& parcel, const label faceI) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -65,7 +65,7 @@ Foam::removeParcel::~removeParcel()
|
|||||||
bool Foam::removeParcel::wallTreatment
|
bool Foam::removeParcel::wallTreatment
|
||||||
(
|
(
|
||||||
parcel&,
|
parcel&,
|
||||||
const label facei
|
const label faceI
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -73,7 +73,7 @@ public:
|
|||||||
|
|
||||||
//- Return true if parcel is to be kept, and false if it is to be
|
//- Return true if parcel is to be kept, and false if it is to be
|
||||||
// removed
|
// removed
|
||||||
bool wallTreatment(parcel& parcel, const label facei) const;
|
bool wallTreatment(parcel& parcel, const label faceI) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -118,7 +118,7 @@ public:
|
|||||||
virtual bool wallTreatment
|
virtual bool wallTreatment
|
||||||
(
|
(
|
||||||
parcel&,
|
parcel&,
|
||||||
const label facei
|
const label faceI
|
||||||
) const = 0;
|
) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -109,57 +109,21 @@ void Foam::DsmcCloud<ParcelType>::initialise
|
|||||||
|
|
||||||
numberDensities /= nParticle_;
|
numberDensities /= nParticle_;
|
||||||
|
|
||||||
forAll(mesh_.cells(), cell)
|
forAll(mesh_.cells(), cellI)
|
||||||
{
|
{
|
||||||
const vector& cC = mesh_.cellCentres()[cell];
|
List<tetIndices> cellTets = polyMeshTetDecomposition::cellTetIndices
|
||||||
const labelList& cellFaces = mesh_.cells()[cell];
|
(
|
||||||
const scalar cV = mesh_.cellVolumes()[cell];
|
mesh_,
|
||||||
|
cellI
|
||||||
|
);
|
||||||
|
|
||||||
label nTets = 0;
|
forAll(cellTets, tetI)
|
||||||
|
|
||||||
// Each face is split into nEdges (or nVertices) - 2 tets.
|
|
||||||
forAll(cellFaces, face)
|
|
||||||
{
|
{
|
||||||
nTets += mesh_.faces()[cellFaces[face]].size() - 2;
|
const tetIndices& cellTetIs = cellTets[tetI];
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the cumulative tet volumes circulating around the cell and
|
tetPointRef tet = cellTetIs.tet(mesh_);
|
||||||
// record the vertex labels of each.
|
|
||||||
scalarList cTetVFracs(nTets, 0.0);
|
|
||||||
|
|
||||||
List<labelList> tetPtIs(nTets, labelList(3,-1));
|
scalar tetVolume = tet.mag();
|
||||||
|
|
||||||
// Keep track of which tet this is.
|
|
||||||
label tet = 0;
|
|
||||||
|
|
||||||
forAll(cellFaces, face)
|
|
||||||
{
|
|
||||||
const labelList& facePoints = mesh_.faces()[cellFaces[face]];
|
|
||||||
|
|
||||||
label pointI = 1;
|
|
||||||
while ((pointI + 1) < facePoints.size())
|
|
||||||
{
|
|
||||||
|
|
||||||
const vector& pA = mesh_.points()[facePoints[0]];
|
|
||||||
const vector& pB = mesh_.points()[facePoints[pointI]];
|
|
||||||
const vector& pC = mesh_.points()[facePoints[pointI + 1]];
|
|
||||||
|
|
||||||
cTetVFracs[tet] =
|
|
||||||
mag(((pA - cC) ^ (pB - cC)) & (pC - cC))/(cV*6.0)
|
|
||||||
+ cTetVFracs[max((tet - 1),0)];
|
|
||||||
|
|
||||||
tetPtIs[tet][0] = facePoints[0];
|
|
||||||
tetPtIs[tet][1] = facePoints[pointI];
|
|
||||||
tetPtIs[tet][2] = facePoints[pointI + 1];
|
|
||||||
|
|
||||||
pointI++;
|
|
||||||
tet++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Force the last volume fraction value to 1.0 to avoid any
|
|
||||||
// rounding/non-flat face errors giving a value < 1.0
|
|
||||||
cTetVFracs[nTets - 1] = 1.0;
|
|
||||||
|
|
||||||
forAll(molecules, i)
|
forAll(molecules, i)
|
||||||
{
|
{
|
||||||
@ -180,67 +144,25 @@ void Foam::DsmcCloud<ParcelType>::initialise
|
|||||||
scalar numberDensity = numberDensities[i];
|
scalar numberDensity = numberDensities[i];
|
||||||
|
|
||||||
// Calculate the number of particles required
|
// Calculate the number of particles required
|
||||||
scalar particlesRequired = numberDensity*mesh_.cellVolumes()[cell];
|
scalar particlesRequired = numberDensity*tetVolume;
|
||||||
|
|
||||||
// Only integer numbers of particles can be inserted
|
// Only integer numbers of particles can be inserted
|
||||||
label nParticlesToInsert = label(particlesRequired);
|
label nParticlesToInsert = label(particlesRequired);
|
||||||
|
|
||||||
// Add another particle with a probability proportional to the
|
// Add another particle with a probability proportional to the
|
||||||
// remainder of taking the integer part of particlesRequired
|
// remainder of taking the integer part of particlesRequired
|
||||||
if ((particlesRequired - nParticlesToInsert) > rndGen_.scalar01())
|
if
|
||||||
|
(
|
||||||
|
(particlesRequired - nParticlesToInsert)
|
||||||
|
> rndGen_.scalar01()
|
||||||
|
)
|
||||||
{
|
{
|
||||||
nParticlesToInsert++;
|
nParticlesToInsert++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (label pI = 0; pI < nParticlesToInsert; pI++)
|
for (label pI = 0; pI < nParticlesToInsert; pI++)
|
||||||
{
|
{
|
||||||
// Choose a random point in a generic tetrahedron
|
point p = tet.randomPoint(rndGen_);
|
||||||
|
|
||||||
scalar s = rndGen_.scalar01();
|
|
||||||
scalar t = rndGen_.scalar01();
|
|
||||||
scalar u = rndGen_.scalar01();
|
|
||||||
|
|
||||||
if (s + t > 1.0)
|
|
||||||
{
|
|
||||||
s = 1.0 - s;
|
|
||||||
t = 1.0 - t;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t + u > 1.0)
|
|
||||||
{
|
|
||||||
scalar tmp = u;
|
|
||||||
u = 1.0 - s - t;
|
|
||||||
t = 1.0 - tmp;
|
|
||||||
}
|
|
||||||
else if (s + t + u > 1.0)
|
|
||||||
{
|
|
||||||
scalar tmp = u;
|
|
||||||
u = s + t + u - 1.0;
|
|
||||||
s = 1.0 - t - tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Choose a tetrahedron to insert in, based on their relative
|
|
||||||
// volumes
|
|
||||||
scalar tetSelection = rndGen_.scalar01();
|
|
||||||
|
|
||||||
// Selected tetrahedron
|
|
||||||
label sTet = -1;
|
|
||||||
|
|
||||||
forAll(cTetVFracs, tet)
|
|
||||||
{
|
|
||||||
sTet = tet;
|
|
||||||
|
|
||||||
if (cTetVFracs[tet] >= tetSelection)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vector p =
|
|
||||||
(1 - s - t - u)*cC
|
|
||||||
+ s*mesh_.points()[tetPtIs[sTet][0]]
|
|
||||||
+ t*mesh_.points()[tetPtIs[sTet][1]]
|
|
||||||
+ u*mesh_.points()[tetPtIs[sTet][2]];
|
|
||||||
|
|
||||||
vector U = equipartitionLinearVelocity
|
vector U = equipartitionLinearVelocity
|
||||||
(
|
(
|
||||||
@ -261,12 +183,15 @@ void Foam::DsmcCloud<ParcelType>::initialise
|
|||||||
p,
|
p,
|
||||||
U,
|
U,
|
||||||
Ei,
|
Ei,
|
||||||
cell,
|
cellI,
|
||||||
|
cellTetIs.face(),
|
||||||
|
cellTetIs.tetPt(),
|
||||||
typeId
|
typeId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialise the sigmaTcRMax_ field to the product of the cross section of
|
// Initialise the sigmaTcRMax_ field to the product of the cross section of
|
||||||
// the most abundant species and the most probable thermal speed (Bird,
|
// the most abundant species and the most probable thermal speed (Bird,
|
||||||
@ -306,9 +231,9 @@ void Foam::DsmcCloud<ParcelType>::collisions()
|
|||||||
|
|
||||||
label collisions = 0;
|
label collisions = 0;
|
||||||
|
|
||||||
forAll(cellOccupancy_, celli)
|
forAll(cellOccupancy_, cellI)
|
||||||
{
|
{
|
||||||
const DynamicList<ParcelType*>& cellParcels(cellOccupancy_[celli]);
|
const DynamicList<ParcelType*>& cellParcels(cellOccupancy_[cellI]);
|
||||||
|
|
||||||
label nC(cellParcels.size());
|
label nC(cellParcels.size());
|
||||||
|
|
||||||
@ -327,13 +252,13 @@ void Foam::DsmcCloud<ParcelType>::collisions()
|
|||||||
// Inverse addressing specifying which subCell a parcel is in
|
// Inverse addressing specifying which subCell a parcel is in
|
||||||
List<label> whichSubCell(cellParcels.size());
|
List<label> whichSubCell(cellParcels.size());
|
||||||
|
|
||||||
const point& cC = mesh_.cellCentres()[celli];
|
const point& cC = mesh_.cellCentres()[cellI];
|
||||||
|
|
||||||
forAll(cellParcels, i)
|
forAll(cellParcels, i)
|
||||||
{
|
{
|
||||||
ParcelType* p = cellParcels[i];
|
const ParcelType& p = *cellParcels[i];
|
||||||
|
|
||||||
vector relPos = p->position() - cC;
|
vector relPos = p.position() - cC;
|
||||||
|
|
||||||
label subCell =
|
label subCell =
|
||||||
pos(relPos.x()) + 2*pos(relPos.y()) + 4*pos(relPos.z());
|
pos(relPos.x()) + 2*pos(relPos.y()) + 4*pos(relPos.z());
|
||||||
@ -345,16 +270,16 @@ void Foam::DsmcCloud<ParcelType>::collisions()
|
|||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
scalar sigmaTcRMax = sigmaTcRMax_[celli];
|
scalar sigmaTcRMax = sigmaTcRMax_[cellI];
|
||||||
|
|
||||||
scalar selectedPairs =
|
scalar selectedPairs =
|
||||||
collisionSelectionRemainder_[celli]
|
collisionSelectionRemainder_[cellI]
|
||||||
+ 0.5*nC*(nC - 1)*nParticle_*sigmaTcRMax*deltaT
|
+ 0.5*nC*(nC - 1)*nParticle_*sigmaTcRMax*deltaT
|
||||||
/mesh_.cellVolumes()[celli];
|
/mesh_.cellVolumes()[cellI];
|
||||||
|
|
||||||
label nCandidates(selectedPairs);
|
label nCandidates(selectedPairs);
|
||||||
|
|
||||||
collisionSelectionRemainder_[celli] = selectedPairs - nCandidates;
|
collisionSelectionRemainder_[cellI] = selectedPairs - nCandidates;
|
||||||
|
|
||||||
collisionCandidates += nCandidates;
|
collisionCandidates += nCandidates;
|
||||||
|
|
||||||
@ -415,39 +340,30 @@ void Foam::DsmcCloud<ParcelType>::collisions()
|
|||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
ParcelType* parcelP = cellParcels[candidateP];
|
ParcelType& parcelP = *cellParcels[candidateP];
|
||||||
ParcelType* parcelQ = cellParcels[candidateQ];
|
ParcelType& parcelQ = *cellParcels[candidateQ];
|
||||||
|
|
||||||
label typeIdP = parcelP->typeId();
|
|
||||||
label typeIdQ = parcelQ->typeId();
|
|
||||||
|
|
||||||
scalar sigmaTcR = binaryCollision().sigmaTcR
|
scalar sigmaTcR = binaryCollision().sigmaTcR
|
||||||
(
|
(
|
||||||
typeIdP,
|
parcelP,
|
||||||
typeIdQ,
|
parcelQ
|
||||||
parcelP->U(),
|
|
||||||
parcelQ->U()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update the maximum value of sigmaTcR stored, but use the
|
// Update the maximum value of sigmaTcR stored, but use the
|
||||||
// initial value in the acceptance-rejection criteria because
|
// initial value in the acceptance-rejection criteria because
|
||||||
// the number of collision candidates selected was based on this
|
// the number of collision candidates selected was based on this
|
||||||
|
|
||||||
if (sigmaTcR > sigmaTcRMax_[celli])
|
if (sigmaTcR > sigmaTcRMax_[cellI])
|
||||||
{
|
{
|
||||||
sigmaTcRMax_[celli] = sigmaTcR;
|
sigmaTcRMax_[cellI] = sigmaTcR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sigmaTcR/sigmaTcRMax) > rndGen_.scalar01())
|
if ((sigmaTcR/sigmaTcRMax) > rndGen_.scalar01())
|
||||||
{
|
{
|
||||||
binaryCollision().collide
|
binaryCollision().collide
|
||||||
(
|
(
|
||||||
typeIdP,
|
parcelP,
|
||||||
typeIdQ,
|
parcelQ
|
||||||
parcelP->U(),
|
|
||||||
parcelQ->U(),
|
|
||||||
parcelP->Ei(),
|
|
||||||
parcelQ->Ei()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
collisions++;
|
collisions++;
|
||||||
@ -577,7 +493,9 @@ void Foam::DsmcCloud<ParcelType>::addNewParcel
|
|||||||
const vector& position,
|
const vector& position,
|
||||||
const vector& U,
|
const vector& U,
|
||||||
const scalar Ei,
|
const scalar Ei,
|
||||||
const label cellId,
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI,
|
||||||
const label typeId
|
const label typeId
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -587,7 +505,9 @@ void Foam::DsmcCloud<ParcelType>::addNewParcel
|
|||||||
position,
|
position,
|
||||||
U,
|
U,
|
||||||
Ei,
|
Ei,
|
||||||
cellId,
|
cellI,
|
||||||
|
tetFaceI,
|
||||||
|
tetPtI,
|
||||||
typeId
|
typeId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -214,6 +214,10 @@ public:
|
|||||||
virtual ~DsmcCloud();
|
virtual ~DsmcCloud();
|
||||||
|
|
||||||
|
|
||||||
|
//- Type of parcel the cloud was instantiated for
|
||||||
|
typedef ParcelType parcelType;
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
// Access
|
||||||
@ -452,7 +456,9 @@ public:
|
|||||||
const vector& position,
|
const vector& position,
|
||||||
const vector& U,
|
const vector& U,
|
||||||
const scalar Ei,
|
const scalar Ei,
|
||||||
const label cellId,
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI,
|
||||||
const label typeId
|
const label typeId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -92,7 +92,9 @@ bool Foam::DsmcParcel<ParcelType>::hitPatch
|
|||||||
(
|
(
|
||||||
const polyPatch&,
|
const polyPatch&,
|
||||||
TrackData& td,
|
TrackData& td,
|
||||||
const label patchI
|
const label,
|
||||||
|
const scalar,
|
||||||
|
const tetIndices&
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -125,7 +127,8 @@ template<class TrackData>
|
|||||||
void Foam::DsmcParcel<ParcelType>::hitWallPatch
|
void Foam::DsmcParcel<ParcelType>::hitWallPatch
|
||||||
(
|
(
|
||||||
const wallPolyPatch& wpp,
|
const wallPolyPatch& wpp,
|
||||||
TrackData& td
|
TrackData& td,
|
||||||
|
const tetIndices& tetIs
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
label wppIndex = wpp.index();
|
label wppIndex = wpp.index();
|
||||||
@ -171,11 +174,8 @@ void Foam::DsmcParcel<ParcelType>::hitWallPatch
|
|||||||
|
|
||||||
td.cloud().wallInteraction().correct
|
td.cloud().wallInteraction().correct
|
||||||
(
|
(
|
||||||
wpp,
|
static_cast<ParcelType&>(*this),
|
||||||
this->face(),
|
wpp
|
||||||
U_,
|
|
||||||
Ei_,
|
|
||||||
typeId_
|
|
||||||
);
|
);
|
||||||
|
|
||||||
U_dot_nw = U_ & nw;
|
U_dot_nw = U_ & nw;
|
||||||
@ -219,7 +219,8 @@ template<class ParcelType>
|
|||||||
void Foam::DsmcParcel<ParcelType>::hitWallPatch
|
void Foam::DsmcParcel<ParcelType>::hitWallPatch
|
||||||
(
|
(
|
||||||
const wallPolyPatch&,
|
const wallPolyPatch&,
|
||||||
int&
|
int&,
|
||||||
|
const tetIndices&
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|||||||
@ -185,7 +185,9 @@ public:
|
|||||||
const vector& position,
|
const vector& position,
|
||||||
const vector& U,
|
const vector& U,
|
||||||
const scalar Ei,
|
const scalar Ei,
|
||||||
const label celli,
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI,
|
||||||
const label typeId
|
const label typeId
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -244,7 +246,9 @@ public:
|
|||||||
(
|
(
|
||||||
const polyPatch&,
|
const polyPatch&,
|
||||||
TrackData& td,
|
TrackData& td,
|
||||||
const label patchI
|
const label patchI,
|
||||||
|
const scalar trackFraction,
|
||||||
|
const tetIndices& tetIs
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Overridable function to handle the particle hitting a
|
//- Overridable function to handle the particle hitting a
|
||||||
@ -269,7 +273,8 @@ public:
|
|||||||
void hitWallPatch
|
void hitWallPatch
|
||||||
(
|
(
|
||||||
const wallPolyPatch&,
|
const wallPolyPatch&,
|
||||||
TrackData& td
|
TrackData& td,
|
||||||
|
const tetIndices&
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Overridable function to handle the particle hitting a wallPatch
|
//- Overridable function to handle the particle hitting a wallPatch
|
||||||
@ -277,7 +282,8 @@ public:
|
|||||||
void hitWallPatch
|
void hitWallPatch
|
||||||
(
|
(
|
||||||
const wallPolyPatch&,
|
const wallPolyPatch&,
|
||||||
int&
|
int&,
|
||||||
|
const tetIndices&
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Overridable function to handle the particle hitting a polyPatch
|
//- Overridable function to handle the particle hitting a polyPatch
|
||||||
@ -352,4 +358,3 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|
||||||
|
|||||||
@ -69,11 +69,13 @@ inline Foam::DsmcParcel<ParcelType>::DsmcParcel
|
|||||||
const vector& position,
|
const vector& position,
|
||||||
const vector& U,
|
const vector& U,
|
||||||
const scalar Ei,
|
const scalar Ei,
|
||||||
const label celli,
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI,
|
||||||
const label typeId
|
const label typeId
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
Particle<ParcelType>(owner, position, celli),
|
Particle<ParcelType>(owner, position, cellI, tetFaceI, tetPtI),
|
||||||
U_(U),
|
U_(U),
|
||||||
Ei_(Ei),
|
Ei_(Ei),
|
||||||
typeId_(typeId)
|
typeId_(typeId)
|
||||||
|
|||||||
@ -43,7 +43,9 @@ Foam::dsmcParcel::dsmcParcel
|
|||||||
const vector& position,
|
const vector& position,
|
||||||
const vector& U,
|
const vector& U,
|
||||||
const scalar Ei,
|
const scalar Ei,
|
||||||
const label celli,
|
const label cellI,
|
||||||
|
const label tetFaceI,
|
||||||
|
const label tetPtI,
|
||||||
const label typeId
|
const label typeId
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
@ -53,7 +55,9 @@ Foam::dsmcParcel::dsmcParcel
|
|||||||
position,
|
position,
|
||||||
U,
|
U,
|
||||||
Ei,
|
Ei,
|
||||||
celli,
|
cellI,
|
||||||
|
tetFaceI,
|
||||||
|
tetPtI,
|
||||||
typeId
|
typeId
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user