Lagrangian: Rewrite of the particle tracking algorithm to function in

terms of the local barycentric coordinates of the current tetrahedron,
rather than the global coordinate system.

Barycentric tracking works on any mesh, irrespective of mesh quality.
Particles do not get "lost", and tracking does not require ad-hoc
"corrections" or "rescues" to function robustly, because the calculation
of particle-face intersections is unambiguous and reproducible, even at
small angles of incidence.

Each particle position is defined by topology (i.e. the decomposed tet
cell it is in) and geometry (i.e. where it is in the cell). No search
operations are needed on restart or reconstruct, unlike when particle
positions are stored in the global coordinate system.

The particle positions file now contains particles' local coordinates
and topology, rather than the global coordinates and cell. This change
to the output format is not backwards compatible. Existing cases with
Lagrangian data will not restart, but they will still run from time
zero without any modification. This change was necessary in order to
guarantee that the loaded particle is valid, and therefore
fundamentally prevent "loss" and "search-failure" type bugs (e.g.,
2517, 2442, 2286, 1836, 1461, 1341, 1097).

The tracking functions have also been converted to function in terms
of displacement, rather than end position. This helps remove floating
point error issues, particularly towards the end of a tracking step.

Wall bounded streamlines have been removed. The implementation proved
incompatible with the new tracking algorithm. ParaView has a surface
LIC plugin which provides equivalent, or better, functionality.

Additionally, bug report <https://bugs.openfoam.org/view.php?id=2517>
is resolved by this change.
This commit is contained in:
Will Bainbridge
2017-04-28 08:03:44 +01:00
committed by Andrew Heather
parent dd3be135de
commit 743dea87d2
91 changed files with 3209 additions and 2443 deletions

View File

@ -77,6 +77,9 @@ int main(int argc, char *argv[])
Info<< "Time = " << runTime.timeName() << nl << endl;
// Store the particle positions
kinematicCloud.storeGlobalPositions();
mesh.update();
// Calculate absolute flux from the mapped surface velocity

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -68,6 +68,8 @@ int main(int argc, char *argv[])
{
Info<< "Time = " << runTime.timeName() << nl << endl;
kinematicCloud.storeGlobalPositions();
mesh.update();
U.correctBoundaryConditions();

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2015-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2015-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -91,6 +91,9 @@ int main(int argc, char *argv[])
// Store momentum to set rhoUf for introduced faces.
volVectorField rhoU("rhoU", rho*U);
// Store the particle positions
parcels.storeGlobalPositions();
// Do any mesh changes
mesh.update();

View File

@ -0,0 +1,3 @@
uncoupledKinematicParcelDyMFoam.C
EXE = $(FOAM_APPBIN)/uncoupledKinematicParcelDyMFoam

View File

@ -0,0 +1,36 @@
EXE_INC = \
-I.. \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/lagrangian/intermediate/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \
-I$(LIB_SRC)/transportModels/compressible/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/reactionThermo/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/radiation/lnInclude \
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
-I$(LIB_SRC)/TurbulenceModels/compressible/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/regionModels/regionModel/lnInclude \
-I$(LIB_SRC)/regionModels/surfaceFilmModels/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/dynamicFvMesh/lnInclude
EXE_LIBS = \
-llagrangian \
-llagrangianIntermediate \
-llagrangianTurbulence \
-lcompressibleTransportModels \
-lfluidThermophysicalModels \
-lspecie \
-lradiationModels \
-lturbulenceModels \
-lcompressibleTurbulenceModels \
-lfiniteVolume \
-lfvOptions \
-lmeshTools \
-lregionModels \
-lsurfaceFilmModels \
-ldynamicMesh \
-ldynamicFvMesh \
-ltopoChangerFvMesh

View File

@ -0,0 +1,90 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
uncoupledKinematicParcelDyMFoam
Description
Transient solver for the passive transport of a particle cloud.
Uses a pre- calculated velocity field to evolve the cloud.
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "dynamicFvMesh.H"
#include "psiThermo.H"
#include "turbulentFluidThermoModel.H"
#include "basicKinematicCloud.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::addOption
(
"cloudName",
"name",
"specify alternative cloud name. default is 'kinematicCloud'"
);
#define NO_CONTROL
#include "postProcess.H"
#include "setRootCase.H"
#include "createTime.H"
#include "createDynamicFvMesh.H"
#include "createFields.H"
#include "compressibleCourantNo.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Info<< "\nStarting time loop\n" << endl;
while (runTime.loop())
{
Info<< "Time = " << runTime.timeName() << nl << endl;
kinematicCloud.storeGlobalPositions();
mesh.update();
U.correctBoundaryConditions();
Info<< "Evolving " << kinematicCloud.name() << endl;
kinematicCloud.evolve();
runTime.write();
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
<< nl << endl;
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -47,13 +47,12 @@ Foam::lagrangianFieldDecomposer::lagrangianFieldDecomposer
{
label pi = 0;
// faceProcAddressing not required currently
// labelList decodedProcFaceAddressing(faceProcAddressing.size());
labelList decodedProcFaceAddressing(faceProcAddressing.size());
// forAll(faceProcAddressing, i)
// {
// decodedProcFaceAddressing[i] = mag(faceProcAddressing[i]) - 1;
// }
forAll(faceProcAddressing, i)
{
decodedProcFaceAddressing[i] = mag(faceProcAddressing[i]) - 1;
}
forAll(cellProcAddressing, procCelli)
{
@ -68,27 +67,28 @@ Foam::lagrangianFieldDecomposer::lagrangianFieldDecomposer
const indexedParticle& ppi = *iter();
particleIndices_[pi++] = ppi.index();
// label mappedTetFace = findIndex
// (
// decodedProcFaceAddressing,
// ppi.tetFace()
// );
label mappedTetFace = findIndex
(
decodedProcFaceAddressing,
ppi.tetFace()
);
// if (mappedTetFace == -1)
// {
// FatalErrorInFunction
// << "Face lookup failure." << nl
// << abort(FatalError);
// }
if (mappedTetFace == -1)
{
FatalErrorInFunction
<< "Face lookup failure." << nl
<< abort(FatalError);
}
positions_.append
(
new passiveParticle
(
procMesh,
ppi.position(),
ppi.coordinates(),
procCelli,
false
mappedTetFace,
ppi.procTetPt(procMesh, procCelli, mappedTetFace)
)
);
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -98,7 +98,6 @@ void mapLagrangian(const meshToMesh0& meshToMesh0Interp)
const fvMesh& meshSource = meshToMesh0Interp.fromMesh();
const fvMesh& meshTarget = meshToMesh0Interp.toMesh();
const pointField& targetCc = meshTarget.cellCentres();
fileNameList cloudDirs
@ -182,15 +181,17 @@ void mapLagrangian(const meshToMesh0& meshToMesh0Interp)
new passiveParticle
(
meshTarget,
targetCc[targetCells[i]],
targetCells[i]
barycentric(1, 0, 0, 0),
targetCells[i],
meshTarget.cells()[targetCells[i]][0],
1
)
);
passiveParticle& newP = newPtr();
label facei = newP.track(iter().position(), td);
newP.track(iter().position() - newP.position(), 0);
if (facei < 0 && newP.cell() >= 0)
if (!newP.onFace())
{
// Hit position.
foundCell = true;
@ -233,11 +234,16 @@ void mapLagrangian(const meshToMesh0& meshToMesh0Interp)
{
unmappedSource.erase(sourceParticleI);
addParticles.append(sourceParticleI);
iter().cell() = targetCell;
targetParcels.addParticle
(
sourceParcels.remove(&iter())
new passiveParticle
(
meshTarget,
iter().position(),
targetCell
)
);
sourceParcels.remove(&iter());
}
}
sourceParticleI++;

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -89,8 +89,6 @@ void mapLagrangian(const meshToMesh& interp)
const polyMesh& meshTarget = interp.tgtRegion();
const labelListList& sourceToTarget = interp.srcToTgtCellAddr();
const pointField& targetCc = meshTarget.cellCentres();
fileNameList cloudDirs
(
readDir
@ -173,15 +171,17 @@ void mapLagrangian(const meshToMesh& interp)
new passiveParticle
(
meshTarget,
targetCc[targetCells[i]],
targetCells[i]
barycentric(1, 0, 0, 0),
targetCells[i],
meshTarget.cells()[targetCells[i]][0],
1
)
);
passiveParticle& newP = newPtr();
label facei = newP.track(iter().position(), td);
newP.track(iter().position() - newP.position(), 0);
if (facei < 0 && newP.cell() >= 0)
if (!newP.onFace())
{
// Hit position.
foundCell = true;
@ -224,11 +224,16 @@ void mapLagrangian(const meshToMesh& interp)
{
unmappedSource.erase(sourceParticleI);
addParticles.append(sourceParticleI);
iter().cell() = targetCell;
targetParcels.addParticle
(
sourceParcels.remove(&iter())
new passiveParticle
(
meshTarget,
iter().position(),
targetCell
)
);
sourceParcels.remove(&iter());
}
}
sourceParticleI++;

View File

@ -33,8 +33,7 @@ minVol 1e-13;
//- Minimum quality of the tet formed by the face-centre
// and variable base point minimum decomposition triangles and
// the cell centre. This has to be a positive number for tracking
// to work. Set to very negative number (e.g. -1E30) to
// the cell centre. Set to very negative number (e.g. -1E30) to
// disable.
// <0 = inside out tet,
// 0 = flat tet

View File

@ -133,6 +133,8 @@ $(spatialVectorAlgebra)/CompactSpatialTensor/compactSpatialTensor/compactSpatial
primitives/polynomialEqns/cubicEqn/cubicEqn.C
primitives/polynomialEqns/quadraticEqn/quadraticEqn.C
primitives/Barycentric/barycentric/barycentric.C
containers/HashTables/HashTable/HashTableCore.C
containers/HashTables/StaticHashTable/StaticHashTableCore.C
containers/Lists/SortableList/ParSortableListName.C

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -135,6 +135,29 @@ void Foam::polyMesh::calcDirections() const
}
Foam::autoPtr<Foam::labelIOList> Foam::polyMesh::readTetBasePtIs() const
{
IOobject io
(
"tetBasePtIs",
instance(),
meshSubDir,
*this,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE
);
if (io.headerOk())
{
return autoPtr<labelIOList>(new labelIOList(io));
}
else
{
return autoPtr<labelIOList>(nullptr);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::polyMesh::polyMesh(const IOobject& io)
@ -207,7 +230,7 @@ Foam::polyMesh::polyMesh(const IOobject& io)
comm_(UPstream::worldComm),
geometricD_(Zero),
solutionD_(Zero),
tetBasePtIsPtr_(nullptr),
tetBasePtIsPtr_(readTetBasePtIs()),
cellTreePtr_(nullptr),
pointZones_
(
@ -401,7 +424,7 @@ Foam::polyMesh::polyMesh
comm_(UPstream::worldComm),
geometricD_(Zero),
solutionD_(Zero),
tetBasePtIsPtr_(nullptr),
tetBasePtIsPtr_(readTetBasePtIs()),
cellTreePtr_(nullptr),
pointZones_
(
@ -552,7 +575,7 @@ Foam::polyMesh::polyMesh
comm_(UPstream::worldComm),
geometricD_(Zero),
solutionD_(Zero),
tetBasePtIsPtr_(nullptr),
tetBasePtIsPtr_(readTetBasePtIs()),
cellTreePtr_(nullptr),
pointZones_
(
@ -815,7 +838,7 @@ Foam::label Foam::polyMesh::nSolutionD() const
}
const Foam::labelList& Foam::polyMesh::tetBasePtIs() const
const Foam::labelIOList& Foam::polyMesh::tetBasePtIs() const
{
if (tetBasePtIsPtr_.empty())
{
@ -828,8 +851,17 @@ const Foam::labelList& Foam::polyMesh::tetBasePtIs() const
tetBasePtIsPtr_.reset
(
new labelList
new labelIOList
(
IOobject
(
"tetBasePtIs",
instance(),
meshSubDir,
*this,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE
),
polyMeshTetDecomposition::findFaceBasePts(*this)
)
);
@ -1105,6 +1137,13 @@ Foam::tmp<Foam::scalarField> Foam::polyMesh::movePoints
points_.instance() = time().timeName();
points_.eventNo() = getEvent();
if (tetBasePtIsPtr_.valid())
{
tetBasePtIsPtr_().writeOpt() = IOobject::AUTO_WRITE;
tetBasePtIsPtr_().instance() = time().timeName();
tetBasePtIsPtr_().eventNo() = getEvent();
}
tmp<scalarField> sweptVols = primitiveMesh::movePoints
(
points_,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -150,7 +150,7 @@ private:
mutable Vector<label> solutionD_;
//- Base point for face decomposition into tets
mutable autoPtr<labelList> tetBasePtIsPtr_;
mutable autoPtr<labelIOList> tetBasePtIsPtr_;
//- Search tree to allow spatial cell searching
mutable autoPtr<indexedOctree<treeDataCell>> cellTreePtr_;
@ -208,6 +208,9 @@ private:
// polyhedral information
void calcCellShapes() const;
//- Read and return the tetBasePtIs
autoPtr<labelIOList> readTetBasePtIs() const;
// Helper functions for constructor from cell shapes
@ -449,7 +452,7 @@ public:
label nSolutionD() const;
//- Return the tetBasePtIs
const labelList& tetBasePtIs() const;
const labelIOList& tetBasePtIs() const;
//- Return the cell search tree
const indexedOctree<treeDataCell>& cellTree() const;
@ -605,8 +608,8 @@ public:
//- Clear primitive data (points, faces and cells)
void clearPrimitives();
//- Clear geometry not used for CFD (cellTree, tetBasePtIs)
void clearAdditionalGeom();
//- Clear tet base points
void clearTetBasePtIs();
//- Clear cell tree data
void clearCellTree();

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -69,22 +69,6 @@ void Foam::polyMesh::clearGeom()
geometricD_ = Zero;
solutionD_ = Zero;
// Remove the stored tet base points
tetBasePtIsPtr_.clear();
// Remove the cell tree
cellTreePtr_.clear();
}
void Foam::polyMesh::clearAdditionalGeom()
{
if (debug)
{
InfoInFunction << "Clearing additional geometric data" << endl;
}
// Remove the stored tet base points
tetBasePtIsPtr_.clear();
// Remove the cell tree
cellTreePtr_.clear();
}
@ -170,6 +154,17 @@ void Foam::polyMesh::clearOut()
}
void Foam::polyMesh::clearTetBasePtIs()
{
if (debug)
{
InfoInFunction << "Clearing tet base points" << endl;
}
tetBasePtIsPtr_.clear();
}
void Foam::polyMesh::clearCellTree()
{
if (debug)

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -59,6 +59,12 @@ void Foam::polyMesh::setInstance(const fileName& inst)
cellZones_.writeOpt() = IOobject::AUTO_WRITE;
cellZones_.instance() = inst;
if (tetBasePtIsPtr_.valid())
{
tetBasePtIsPtr_->writeOpt() = IOobject::AUTO_WRITE;
tetBasePtIsPtr_->instance() = inst;
}
}
@ -387,6 +393,9 @@ Foam::polyMesh::readUpdateState Foam::polyMesh::readUpdate()
cellZones_.set(czI, newCellZones[czI].clone(cellZones_));
}
// Re-read tet base points
tetBasePtIsPtr_ = readTetBasePtIs();
if (boundaryChanged)
{
@ -439,6 +448,13 @@ Foam::polyMesh::readUpdateState Foam::polyMesh::readUpdate()
points_.transfer(newPoints);
points_.instance() = pointsInst;
// Re-read tet base points
autoPtr<labelIOList> newTetBasePtIsPtr = readTetBasePtIs();
if (newTetBasePtIsPtr.valid())
{
tetBasePtIsPtr_ = newTetBasePtIsPtr;
}
// Calculate the geometry for the patches (transformation tensors etc.)
boundary_.calcGeometry();

View File

@ -0,0 +1,117 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::Barycentric
Description
Templated 3D Barycentric derived from VectorSpace. Has 4 components, one of
which is redundant.
SourceFiles
BarycentricI.H
\*---------------------------------------------------------------------------*/
#ifndef Barycentric_H
#define Barycentric_H
#include "VectorSpace.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class Barycentric Declaration
\*---------------------------------------------------------------------------*/
template<class Cmpt>
class Barycentric
:
public VectorSpace<Barycentric<Cmpt>, Cmpt, 4>
{
public:
//- Equivalent type of labels used for valid component indexing
typedef Barycentric<label> labelType;
// Member constants
//- Rank of Barycentric is 1
static const direction rank = 1;
//- Component labeling enumeration
enum components { A, B, C, D };
// Constructors
//- Construct null
inline Barycentric();
//- Construct initialized to zero
inline Barycentric(const Foam::zero);
//- Construct given four components
inline Barycentric
(
const Cmpt& va,
const Cmpt& vb,
const Cmpt& vc,
const Cmpt& vd
);
// Member Functions
// Access
inline const Cmpt& a() const;
inline const Cmpt& b() const;
inline const Cmpt& c() const;
inline const Cmpt& d() const;
inline Cmpt& a();
inline Cmpt& b();
inline Cmpt& c();
inline Cmpt& d();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "BarycentricI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,132 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANB 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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Cmpt>
inline Foam::Barycentric<Cmpt>::Barycentric()
{}
template<class Cmpt>
inline Foam::Barycentric<Cmpt>::Barycentric(const Foam::zero)
:
Barycentric::vsType(Zero)
{}
template<class Cmpt>
inline Foam::Barycentric<Cmpt>::Barycentric
(
const Cmpt& va,
const Cmpt& vb,
const Cmpt& vc,
const Cmpt& vd
)
{
this->v_[A] = va;
this->v_[B] = vb;
this->v_[C] = vc;
this->v_[D] = vd;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Cmpt>
inline const Cmpt& Foam::Barycentric<Cmpt>::a() const
{
return this->v_[A];
}
template<class Cmpt>
inline const Cmpt& Foam::Barycentric<Cmpt>::b() const
{
return this->v_[B];
}
template<class Cmpt>
inline const Cmpt& Foam::Barycentric<Cmpt>::c() const
{
return this->v_[C];
}
template<class Cmpt>
inline const Cmpt& Foam::Barycentric<Cmpt>::d() const
{
return this->v_[D];
}
template<class Cmpt>
inline Cmpt& Foam::Barycentric<Cmpt>::a()
{
return this->v_[A];
}
template<class Cmpt>
inline Cmpt& Foam::Barycentric<Cmpt>::b()
{
return this->v_[B];
}
template<class Cmpt>
inline Cmpt& Foam::Barycentric<Cmpt>::c()
{
return this->v_[C];
}
template<class Cmpt>
inline Cmpt& Foam::Barycentric<Cmpt>::d()
{
return this->v_[D];
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
template<class Cmpt>
inline Cmpt operator&(const Barycentric<Cmpt>& b1, const Barycentric<Cmpt>& b2)
{
return b1.a()*b2.a() + b1.b()*b2.b() + b1.c()*b2.c() + b1.d()*b2.d();
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,139 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::BarycentricTensor
Description
Templated 4x3 tensor derived from VectorSpace. Has 12 components. Can
represent a barycentric transformation as a matrix-barycentric inner-
product. Can alternatively represent an inverse barycentric transformation
as a vector-matrix inner-product.
SourceFiles
BarycentricTensorI.H
\*---------------------------------------------------------------------------*/
#ifndef BarycentricTensor_H
#define BarycentricTensor_H
#include "Barycentric.H"
#include "Tensor.H"
#include "Vector.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class BarycentricTensor Declaration
\*---------------------------------------------------------------------------*/
template<class Cmpt>
class BarycentricTensor
:
public MatrixSpace<BarycentricTensor<Cmpt>, Cmpt, 4, 3>
{
public:
//- Equivalent type of labels used for valid component indexing
typedef Tensor<label> labelType;
// Member constants
//- Rank of BarycentricTensor is 2
static const direction rank = 2;
//- Component labeling enumeration
enum components { XA, XB, XC, XD, YA, YB, YC, YD, ZA, ZB, ZC, ZD };
// Constructors
//- Construct null
BarycentricTensor();
//- Construct initialised to zero
BarycentricTensor(const Foam::zero);
//- Construct given three barycentric components (rows)
BarycentricTensor
(
const Barycentric<Cmpt>& x,
const Barycentric<Cmpt>& y,
const Barycentric<Cmpt>& z
);
//- Construct given four vector components (columns)
BarycentricTensor
(
const Vector<Cmpt>& a,
const Vector<Cmpt>& b,
const Vector<Cmpt>& c,
const Vector<Cmpt>& d
);
// Member Functions
// Row-barycentric access
inline Barycentric<Cmpt> x() const;
inline Barycentric<Cmpt> y() const;
inline Barycentric<Cmpt> z() const;
// Column-vector access
inline Vector<Cmpt> a() const;
inline Vector<Cmpt> b() const;
inline Vector<Cmpt> c() const;
inline Vector<Cmpt> d() const;
};
template<class Cmpt>
class typeOfTranspose<Cmpt, BarycentricTensor<Cmpt>>
{
public:
typedef void type;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "BarycentricTensorI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,196 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Cmpt>
inline Foam::BarycentricTensor<Cmpt>::BarycentricTensor()
{}
template<class Cmpt>
inline Foam::BarycentricTensor<Cmpt>::BarycentricTensor(const Foam::zero)
:
BarycentricTensor::msType(Zero)
{}
template<class Cmpt>
inline Foam::BarycentricTensor<Cmpt>::BarycentricTensor
(
const Barycentric<Cmpt>& x,
const Barycentric<Cmpt>& y,
const Barycentric<Cmpt>& z
)
{
this->v_[XA] = x.a();
this->v_[XB] = x.b();
this->v_[XC] = x.c();
this->v_[XD] = x.d();
this->v_[YA] = y.a();
this->v_[YB] = y.b();
this->v_[YC] = y.c();
this->v_[YD] = y.d();
this->v_[ZA] = z.a();
this->v_[ZB] = z.b();
this->v_[ZC] = z.c();
this->v_[ZD] = z.d();
}
template<class Cmpt>
inline Foam::BarycentricTensor<Cmpt>::BarycentricTensor
(
const Vector<Cmpt>& a,
const Vector<Cmpt>& b,
const Vector<Cmpt>& c,
const Vector<Cmpt>& d
)
{
this->v_[XA] = a.x();
this->v_[XB] = b.x();
this->v_[XC] = c.x();
this->v_[XD] = d.x();
this->v_[YA] = a.y();
this->v_[YB] = b.y();
this->v_[YC] = c.y();
this->v_[YD] = d.y();
this->v_[ZA] = a.z();
this->v_[ZB] = b.z();
this->v_[ZC] = c.z();
this->v_[ZD] = d.z();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Cmpt>
inline Foam::Barycentric<Cmpt> Foam::BarycentricTensor<Cmpt>::x() const
{
return
Barycentric<Cmpt>
(
this->v_[XA],
this->v_[XB],
this->v_[XC],
this->v_[XD]
);
}
template<class Cmpt>
inline Foam::Barycentric<Cmpt> Foam::BarycentricTensor<Cmpt>::y() const
{
return
Barycentric<Cmpt>
(
this->v_[YA],
this->v_[YB],
this->v_[YC],
this->v_[YD]
);
}
template<class Cmpt>
inline Foam::Barycentric<Cmpt> Foam::BarycentricTensor<Cmpt>::z() const
{
return
Barycentric<Cmpt>
(
this->v_[ZA],
this->v_[ZB],
this->v_[ZC],
this->v_[ZD]
);
}
template<class Cmpt>
inline Foam::Vector<Cmpt> Foam::BarycentricTensor<Cmpt>::a() const
{
return Vector<Cmpt>(this->v_[XA], this->v_[YA], this->v_[ZA]);
}
template<class Cmpt>
inline Foam::Vector<Cmpt> Foam::BarycentricTensor<Cmpt>::b() const
{
return Vector<Cmpt>(this->v_[XB], this->v_[YB], this->v_[ZB]);
}
template<class Cmpt>
inline Foam::Vector<Cmpt> Foam::BarycentricTensor<Cmpt>::c() const
{
return Vector<Cmpt>(this->v_[XC], this->v_[YC], this->v_[ZC]);
}
template<class Cmpt>
inline Foam::Vector<Cmpt> Foam::BarycentricTensor<Cmpt>::d() const
{
return Vector<Cmpt>(this->v_[XD], this->v_[YD], this->v_[ZD]);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
template<class Cmpt>
inline Vector<Cmpt> operator&
(
const BarycentricTensor<Cmpt>& T,
const Barycentric<Cmpt>& b
)
{
return Vector<Cmpt>(T.x() & b, T.y() & b, T.z() & b);
}
template<class Cmpt>
inline Barycentric<Cmpt> operator&
(
const Vector<Cmpt>& v,
const BarycentricTensor<Cmpt>& T
)
{
return Barycentric<Cmpt>(v & T.a(), v & T.b(), v & T.c(), v & T.d());
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,95 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "barycentric.H"
#include "Random.H"
#include "cachedRandom.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Foam::barycentric barycentric01
(
Foam::scalar s,
Foam::scalar t,
Foam::scalar u
)
{
// Transform the random point in the unit cube to a random point in the
// unit tet by means of a series of reflections. See
// <http://vcg.isti.cnr.it/jgt/tetra.htm> for details.
if (s + t > 1)
{
s = 1 - s;
t = 1 - t;
}
if (s + t + u > 1)
{
Foam::scalar temp = u;
if (t + u > 1)
{
u = 1 - s - t;
t = 1 - temp;
}
else
{
u = s + t + u - 1;
s = 1 - t - temp;
}
}
return Foam::barycentric(1 - s - t - u, s, t, u);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Foam::barycentric Foam::barycentric01(Random& rndGen)
{
return
::barycentric01
(
rndGen.scalar01(),
rndGen.scalar01(),
rndGen.scalar01()
);
}
Foam::barycentric Foam::barycentric01(cachedRandom& rndGen)
{
return
::barycentric01
(
rndGen.sample01<scalar>(),
rndGen.sample01<scalar>(),
rndGen.sample01<scalar>()
);
}
// ************************************************************************* //

View File

@ -0,0 +1,74 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Typedef
Foam::barycentric
Description
A scalar version of the templated Barycentric
\*---------------------------------------------------------------------------*/
#ifndef barycentric_H
#define barycentric_H
#include "scalar.H"
#include "Barycentric.H"
#include "contiguous.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class Random;
class cachedRandom;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
typedef Barycentric<scalar> barycentric;
//- Generate a random barycentric coordinate within the unit tetrahedron
barycentric barycentric01(Random& rndGen);
barycentric barycentric01(cachedRandom& rndGen);
template<>
inline bool contiguous<barycentric>()
{
return true;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,64 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Typedef
Foam::barycentricTensor
Description
A scalar version of the templated BarycentricTensor
\*---------------------------------------------------------------------------*/
#ifndef barycentricTensor_H
#define barycentricTensor_H
#include "scalar.H"
#include "BarycentricTensor.H"
#include "contiguous.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
typedef BarycentricTensor<scalar> barycentricTensor;
template<>
inline bool contiguous<barycentricTensor>()
{
return true;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -92,6 +92,9 @@ public:
//- Evaluate at x
inline scalar value(const scalar x) const;
//- Evaluate the derivative at x
inline scalar derivative(const scalar x) const;
//- Estimate the error of evaluation at x
inline scalar error(const scalar x) const;

View File

@ -106,6 +106,12 @@ inline Foam::scalar Foam::cubicEqn::value(const scalar x) const
}
inline Foam::scalar Foam::cubicEqn::derivative(const scalar x) const
{
return x*(x*3*a() + 2*b()) + c();
}
inline Foam::scalar Foam::cubicEqn::error(const scalar x) const
{
return mag(SMALL*x*(x*(x*3*a() + 2*b()) + c()));

View File

@ -81,6 +81,9 @@ public:
//- Evaluate at x
inline scalar value(const scalar x) const;
//- Evaluate the derivative at x
inline scalar derivative(const scalar x) const;
//- Estimate the error of evaluation at x
inline scalar error(const scalar x) const;

View File

@ -74,6 +74,12 @@ inline Foam::scalar Foam::linearEqn::value(const scalar x) const
}
inline Foam::scalar Foam::linearEqn::derivative(const scalar x) const
{
return a();
}
inline Foam::scalar Foam::linearEqn::error(const scalar x) const
{
return mag(SMALL*x*a());

View File

@ -84,6 +84,9 @@ public:
//- Evaluate at x
inline scalar value(const scalar x) const;
//- Evaluate the derivative at x
inline scalar derivative(const scalar x) const;
//- Estimate the error of evaluation at x
inline scalar error(const scalar x) const;

View File

@ -92,6 +92,12 @@ inline Foam::scalar Foam::quadraticEqn::value(const scalar x) const
}
inline Foam::scalar Foam::quadraticEqn::derivative(const scalar x) const
{
return x*2*a() + b();
}
inline Foam::scalar Foam::quadraticEqn::error(const scalar x) const
{
return mag(SMALL*x*(x*2*a() + b()));

View File

@ -727,7 +727,7 @@ void Foam::motionSmootherAlgo::movePoints()
{
// Make sure to clear out tetPtIs since used in checks (sometimes, should
// really check)
mesh_.clearAdditionalGeom();
mesh_.clearTetBasePtIs();
pp_.movePoints(mesh_.points());
}

View File

@ -25,11 +25,6 @@ streamLine/streamLineBase.C
streamLine/streamLineParticle.C
streamLine/streamLineParticleCloud.C
wallBoundedStreamLine/wallBoundedStreamLine.C
wallBoundedStreamLine/wallBoundedStreamLineParticle.C
wallBoundedStreamLine/wallBoundedStreamLineParticleCloud.C
wallBoundedStreamLine/wallBoundedParticle.C
surfaceInterpolate/surfaceInterpolate.C
regionSizeDistribution/regionSizeDistribution.C

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2013-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2013-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -30,7 +30,7 @@ License
Foam::findCellParticle::findCellParticle
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -38,7 +38,24 @@ Foam::findCellParticle::findCellParticle
const label data
)
:
particle(mesh, position, celli, tetFacei, tetPti),
particle(mesh, coordinates, celli, tetFacei, tetPti),
start_(position()),
end_(end),
data_(data)
{}
Foam::findCellParticle::findCellParticle
(
const polyMesh& mesh,
const vector& position,
const label celli,
const point& end,
const label data
)
:
particle(mesh, position, celli),
start_(this->position()),
end_(end),
data_(data)
{}
@ -57,15 +74,15 @@ Foam::findCellParticle::findCellParticle
{
if (is.format() == IOstream::ASCII)
{
is >> end_;
is >> start_ >> end_;
data_ = readLabel(is);
}
else
{
is.read
(
reinterpret_cast<char*>(&end_),
sizeof(end_) + sizeof(data_)
reinterpret_cast<char*>(&start_),
sizeof(start_) + sizeof(end_) + sizeof(data_)
);
}
}
@ -85,21 +102,13 @@ bool Foam::findCellParticle::move
td.switchProcessor = false;
td.keepParticle = true;
scalar tEnd = (1.0 - stepFraction())*maxTrackLen;
scalar dtMax = tEnd;
while (td.keepParticle && !td.switchProcessor && tEnd > SMALL)
while (td.keepParticle && !td.switchProcessor && stepFraction() < 1)
{
// set the lagrangian time-step
scalar dt = min(dtMax, tEnd);
dt *= trackToFace(end_, td);
tEnd -= dt;
stepFraction() = 1.0 - tEnd/maxTrackLen;
const scalar f = 1 - stepFraction();
trackToFace(f*(end_ - start_), f, td);
}
if (tEnd < SMALL || !td.keepParticle)
if (stepFraction() == 1 || !td.keepParticle)
{
// Hit endpoint or patch. If patch hit could do fancy stuff but just
// to use the patch point is good enough for now.
@ -209,6 +218,7 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const findCellParticle& p)
if (os.format() == IOstream::ASCII)
{
os << static_cast<const particle&>(p)
<< token::SPACE << p.start_
<< token::SPACE << p.end_
<< token::SPACE << p.data_;
}
@ -217,8 +227,8 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const findCellParticle& p)
os << static_cast<const particle&>(p);
os.write
(
reinterpret_cast<const char*>(&p.end_),
sizeof(p.end_) + sizeof(p.data_)
reinterpret_cast<const char*>(&p.start_),
sizeof(p.start_) + sizeof(p.end_) + sizeof(p.data_)
);
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2013-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2013-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -63,6 +63,9 @@ class findCellParticle
{
// Private data
//- Start point to track from
point start_;
//- End point to track to
point end_;
@ -119,7 +122,7 @@ public:
findCellParticle
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -127,6 +130,17 @@ public:
const label data
);
//- Construct from a position and a cell, searching for the rest of the
// required topology
findCellParticle
(
const polyMesh& mesh,
const vector& position,
const label celli,
const point& end,
const label data
);
//- Construct from Istream
findCellParticle
(
@ -166,18 +180,42 @@ public:
// Member Functions
//- Point to track from
const point& start() const
{
return start_;
}
//- Point to track from
point& start()
{
return start_;
}
//- Point to track to
const point& end() const
{
return end_;
}
//- Point to track to
point& end()
{
return end_;
}
//- Transported label
label data() const
{
return data_;
}
//- Transported label
label& data()
{
return data_;
}
// Tracking

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015-2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -126,32 +126,19 @@ void Foam::functionObjects::nearWallFields::calcAddressing()
const point end = start-distance_*nf[patchFacei];
if (tetFacei == -1)
{
WarningInFunction << "Did not find point " << start
<< " inside cell " << celli
<< ". Not seeding particle originating from face centre "
<< mesh_.faceCentres()[meshFacei]
<< " with cell centre " << mesh_.cellCentres()[celli]
<< endl;
}
else
{
// Add to cloud. Add originating face as passive data
// Add a particle to the cloud with originating face as passive data
cloud.addParticle
(
new findCellParticle
(
mesh_,
start,
celli,
tetFacei,
tetPti,
-1,
end,
globalWalls.toGlobal(nPatchFaces) // passive data
)
);
}
nPatchFaces++;
}
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -26,35 +26,8 @@ License
#include "streamLineParticle.H"
#include "vectorFieldIOField.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
// defineParticleTypeNameAndDebug(streamLineParticle, 0);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::scalar Foam::streamLineParticle::calcSubCycleDeltaT
(
trackingData& td,
const scalar dt,
const vector& U
) const
{
particle testParticle(*this);
bool oldKeepParticle = td.keepParticle;
bool oldSwitchProcessor = td.switchProcessor;
scalar fraction = testParticle.trackToFace(position()+dt*U, td);
td.keepParticle = oldKeepParticle;
td.switchProcessor = oldSwitchProcessor;
// Adapt the dt to subdivide the trajectory into substeps.
return dt*fraction/td.nSubCycle_;
}
Foam::vector Foam::streamLineParticle::interpolateFields
(
const trackingData& td,
@ -129,7 +102,6 @@ Foam::streamLineParticle::streamLineParticle
{
if (readFields)
{
//if (is.format() == IOstream::ASCII)
List<scalarList> sampledScalars;
List<vectorList> sampledVectors;
@ -169,31 +141,22 @@ Foam::streamLineParticle::streamLineParticle
bool Foam::streamLineParticle::move
(
trackingData& td,
const scalar trackTime
const scalar
)
{
streamLineParticle& p = static_cast<streamLineParticle&>(*this);
td.switchProcessor = false;
td.keepParticle = true;
scalar tEnd = (1.0 - stepFraction())*trackTime;
scalar maxDt = mesh_.bounds().mag();
const scalar maxDt = mesh().bounds().mag();
while
(
td.keepParticle
&& !td.switchProcessor
&& lifeTime_ > 0
)
while (td.keepParticle && !td.switchProcessor && lifeTime_ > 0)
{
// set the lagrangian time-step
scalar dt = maxDt;
// Cross cell in steps:
// - at subiter 0 calculate dt to cross cell in nSubCycle steps
// - at the last subiter do all of the remaining track
for (label subIter = 0; subIter < td.nSubCycle_; subIter++)
for (label subIter = 0; subIter < max(1, td.nSubCycle_); subIter++)
{
--lifeTime_;
@ -219,37 +182,27 @@ bool Foam::streamLineParticle::move
if (td.trackLength_ < GREAT)
{
// No sub-cycling. Track a set length on each step.
dt = td.trackLength_;
//Pout<< " subiteration " << subIter
// << " : fixed length: updated dt:" << dt << endl;
}
else if (subIter == 0 && td.nSubCycle_ > 1)
else if (subIter == 0)
{
// Adapt dt to cross cell in a few steps
dt = calcSubCycleDeltaT(td, dt, U);
// Sub-cycling. Cross the cell in nSubCycle steps.
particle copy(*this);
copy.trackToFace(maxDt*U, 1);
dt *= (copy.stepFraction() - stepFraction())/td.nSubCycle_;
}
else if (subIter == td.nSubCycle_ - 1)
{
// Do full step on last subcycle
// Sub-cycling. Track the whole cell on the last step.
dt = maxDt;
}
scalar fraction = trackToFace(position() + dt*U, td);
dt *= fraction;
tEnd -= dt;
stepFraction() = 1.0 - tEnd/trackTime;
if (tEnd <= ROOTVSMALL)
{
// Force removal
lifeTime_ = 0;
}
trackToFace(dt*U, 0, td);
if
(
face() != -1
onFace()
|| !td.keepParticle
|| td.switchProcessor
|| lifeTime_ == 0
@ -260,17 +213,16 @@ bool Foam::streamLineParticle::move
}
}
if (!td.keepParticle || lifeTime_ == 0)
{
if (lifeTime_ == 0)
{
// Failure exit. Particle stagnated or it's life ran out.
if (debug)
{
Pout<< "streamLineParticle : Removing stagnant particle:"
<< p.position()
<< " sampled positions:" << sampledPositions_.size()
<< endl;
Pout<< "streamLineParticle: Removing stagnant particle:"
<< position() << " sampled positions:"
<< sampledPositions_.size() << endl;
}
td.keepParticle = false;
}
@ -282,29 +234,25 @@ bool Foam::streamLineParticle::move
if (debug)
{
Pout<< "streamLineParticle : Removing particle:"
<< p.position()
Pout<< "streamLineParticle: Removing particle:" << position()
<< " sampled positions:" << sampledPositions_.size()
<< endl;
}
}
// Transfer particle data into trackingData.
//td.allPositions_.append(sampledPositions_);
td.allPositions_.append(vectorList());
vectorList& top = td.allPositions_.last();
top.transfer(sampledPositions_);
forAll(sampledScalars_, i)
{
//td.allScalars_[i].append(sampledScalars_[i]);
td.allScalars_[i].append(scalarList());
scalarList& top = td.allScalars_[i].last();
top.transfer(sampledScalars_[i]);
}
forAll(sampledVectors_, i)
{
//td.allVectors_[i].append(sampledVectors_[i]);
td.allVectors_[i].append(vectorList());
vectorList& top = td.allVectors_[i].last();
top.transfer(sampledVectors_[i]);
@ -428,18 +376,11 @@ void Foam::streamLineParticle::readFields(Cloud<streamLineParticle>& c)
);
c.checkFieldIOobject(c, sampledPositions);
// vectorFieldIOField sampleVelocity
// (
// c.fieldIOobject("sampleVelocity", IOobject::MUST_READ)
// );
// c.checkFieldIOobject(c, sampleVelocity);
label i = 0;
forAllIter(Cloud<streamLineParticle>, c, iter)
{
iter().lifeTime_ = lifeTime[i];
iter().sampledPositions_.transfer(sampledPositions[i]);
// iter().sampleVelocity_.transfer(sampleVelocity[i]);
i++;
}
}
@ -461,24 +402,17 @@ void Foam::streamLineParticle::writeFields(const Cloud<streamLineParticle>& c)
c.fieldIOobject("sampledPositions", IOobject::NO_READ),
np
);
// vectorFieldIOField sampleVelocity
// (
// c.fieldIOobject("sampleVelocity", IOobject::NO_READ),
// np
// );
label i = 0;
forAllConstIter(Cloud<streamLineParticle>, c, iter)
{
lifeTime[i] = iter().lifeTime_;
sampledPositions[i] = iter().sampledPositions_;
// sampleVelocity[i] = iter().sampleVelocity_;
i++;
}
lifeTime.write();
sampledPositions.write();
// sampleVelocity.write();
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -46,16 +46,12 @@ SourceFiles
namespace Foam
{
class streamLineParticleCloud;
// Forward declaration of friend functions and operators
class streamLineParticle;
Ostream& operator<<(Ostream&, const streamLineParticle&);
/*---------------------------------------------------------------------------*\
Class streamLineParticle Declaration
\*---------------------------------------------------------------------------*/
@ -64,32 +60,38 @@ class streamLineParticle
:
public particle
{
public:
//- Class used to pass tracking data to the trackToFace function
class trackingData
:
public particle::TrackingData<Cloud<streamLineParticle>>
{
public:
// Public data
const PtrList<interpolation<scalar>>& vsInterp_;
const PtrList<interpolation<vector>>& vvInterp_;
const label UIndex_;
const bool trackForward_;
const label nSubCycle_;
const scalar trackLength_;
DynamicList<vectorList>& allPositions_;
List<DynamicList<scalarList>>& allScalars_;
List<DynamicList<vectorList>>& allVectors_;
// Constructors
//- Construct from components
trackingData
(
Cloud<streamLineParticle>& cloud,
@ -99,7 +101,6 @@ public:
const bool trackForward,
const label nSubCycle,
const scalar trackLength,
DynamicList<List<point>>& allPositions,
List<DynamicList<scalarList>>& allScalars,
List<DynamicList<vectorList>>& allVectors
@ -112,7 +113,6 @@ public:
trackForward_(trackForward),
nSubCycle_(nSubCycle),
trackLength_(trackLength),
allPositions_(allPositions),
allScalars_(allScalars),
allVectors_(allVectors)
@ -139,22 +139,6 @@ private:
// Private Member Functions
//- Estimate dt to cross from current face to next one in nSubCycle
// steps.
scalar calcSubCycleDeltaT
(
trackingData& td,
const scalar dt,
const vector& U
) const;
void constrainVelocity
(
trackingData& td,
const scalar dt,
vector& U
);
//- Interpolate all quantities; return interpolated velocity.
vector interpolateFields
(
@ -195,8 +179,7 @@ public:
return autoPtr<particle>(new streamLineParticle(*this));
}
//- Factory class to read-construct particles used for
// parallel transfer
//- Factory class to read-construct particles used for parallel transfer
class iNew
{
const polyMesh& mesh_;
@ -223,8 +206,7 @@ public:
// Tracking
//- Track all particles to their end point
bool move(trackingData&, const scalar trackTime);
bool move(trackingData&, const scalar);
//- Overridable function to handle the particle hitting a patch
// Executed before other patch-hitting functions

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -176,16 +176,7 @@ void Foam::DSMCCloud<ParcelType>::initialise
U += velocity;
addNewParcel
(
p,
U,
Ei,
celli,
cellTetIs.face(),
cellTetIs.tetPt(),
typeId
);
addNewParcel(p, celli, U, Ei, typeId);
}
}
}
@ -465,27 +456,13 @@ template<class ParcelType>
void Foam::DSMCCloud<ParcelType>::addNewParcel
(
const vector& position,
const label celli,
const vector& U,
const scalar Ei,
const label celli,
const label tetFacei,
const label tetPti,
const label typeId
)
{
ParcelType* pPtr = new ParcelType
(
mesh_,
position,
U,
Ei,
celli,
tetFacei,
tetPti,
typeId
);
this->addParticle(pPtr);
this->addParticle(new ParcelType(mesh_, position, celli, U, Ei, typeId));
}
@ -1110,9 +1087,7 @@ void Foam::DSMCCloud<ParcelType>::dumpParticlePositions() const
template<class ParcelType>
void Foam::DSMCCloud<ParcelType>::autoMap(const mapPolyMesh& mapper)
{
typedef typename ParcelType::trackingData tdType;
tdType td(*this);
Cloud<ParcelType>::template autoMap<tdType>(td, mapper);
Cloud<ParcelType>::autoMap(mapper);
// Update the cell occupancy field
cellOccupancy_.setSize(mesh_.nCells());

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -44,6 +44,7 @@ SourceFiles
#include "fvMesh.H"
#include "volFields.H"
#include "scalarIOField.H"
#include "barycentric.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -451,11 +452,9 @@ public:
void addNewParcel
(
const vector& position,
const label celli,
const vector& U,
const scalar Ei,
const label celli,
const label tetFacei,
const label tetPti,
const label typeId
);

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -41,19 +41,16 @@ bool Foam::DSMCParcel<ParcelType>::move(TrackData& td, const scalar trackTime)
const polyMesh& mesh = td.cloud().pMesh();
const polyBoundaryMesh& pbMesh = mesh.boundaryMesh();
scalar tEnd = (1.0 - p.stepFraction())*trackTime;
const scalar dtMax = tEnd;
// For reduced-D cases, the velocity used to track needs to be
// constrained, but the actual U_ of the parcel must not be
// altered or used, as it is altered by patch interactions an
// needs to retain its 3D value for collision purposes.
vector Utracking = U_;
while (td.keepParticle && !td.switchProcessor && tEnd > ROOTVSMALL)
while (td.keepParticle && !td.switchProcessor && p.stepFraction() < 1)
{
// Apply correction to position for reduced-D cases
meshTools::constrainToMeshCentre(mesh, p.position());
p.constrainToMeshCentre();
Utracking = U_;
@ -61,16 +58,10 @@ bool Foam::DSMCParcel<ParcelType>::move(TrackData& td, const scalar trackTime)
// reduced-D cases
meshTools::constrainDirection(mesh, mesh.solutionD(), Utracking);
// Set the Lagrangian time-step
scalar dt = min(dtMax, tEnd);
const scalar f = 1 - p.stepFraction();
p.trackToFace(f*trackTime*Utracking, f, td);
dt *= p.trackToFace(p.position() + dt*Utracking, td);
tEnd -= dt;
p.stepFraction() = 1.0 - tEnd/trackTime;
if (p.onBoundary() && td.keepParticle)
if (p.onBoundaryFace() && td.keepParticle)
{
if (isA<processorPolyPatch>(pbMesh[p.patch(p.face())]))
{

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -176,12 +176,24 @@ public:
inline DSMCParcel
(
const polyMesh& mesh,
const vector& position,
const vector& U,
const scalar Ei,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
const vector& U,
const scalar Ei,
const label typeId
);
//- Construct from a position and a cell, searching for the rest of the
// required topology
inline DSMCParcel
(
const polyMesh& mesh,
const vector& position,
const label celli,
const vector& U,
const scalar Ei,
const label typeId
);

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -55,16 +55,34 @@ template<class ParcelType>
inline Foam::DSMCParcel<ParcelType>::DSMCParcel
(
const polyMesh& mesh,
const vector& position,
const vector& U,
const scalar Ei,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
const vector& U,
const scalar Ei,
const label typeId
)
:
ParcelType(mesh, position, celli, tetFacei, tetPti),
ParcelType(mesh, coordinates, celli, tetFacei, tetPti),
U_(U),
Ei_(Ei),
typeId_(typeId)
{}
template<class ParcelType>
inline Foam::DSMCParcel<ParcelType>::DSMCParcel
(
const polyMesh& mesh,
const vector& position,
const label celli,
const vector& U,
const scalar Ei,
const label typeId
)
:
ParcelType(mesh, position, celli),
U_(U),
Ei_(Ei),
typeId_(typeId)

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -403,16 +403,7 @@ void Foam::FreeStream<CloudType>::inflow()
cloud.constProps(typeId).internalDegreesOfFreedom()
);
cloud.addNewParcel
(
p,
U,
Ei,
celli,
globalFaceIndex,
faceTetIs.tetPt(),
typeId
);
cloud.addNewParcel(p, celli, U, Ei, typeId);
particlesInserted++;
}

View File

@ -105,7 +105,8 @@ Foam::Cloud<ParticleType>::Cloud
polyMesh_(pMesh),
labels_(),
nTrackingRescues_(),
cellWallFacesPtr_()
cellWallFacesPtr_(),
globalPositionsPtr_()
{
checkPatches();
@ -234,6 +235,8 @@ void Foam::Cloud<ParticleType>::move(TrackData& td, const scalar trackTime)
// Allocate transfer buffers
PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
// Clear the global positions as there are about to change
globalPositionsPtr_.clear();
// While there are particles to transfer
while (true)
@ -393,21 +396,16 @@ void Foam::Cloud<ParticleType>::move(TrackData& td, const scalar trackTime)
template<class ParticleType>
template<class TrackData>
void Foam::Cloud<ParticleType>::autoMap
(
TrackData& td,
const mapPolyMesh& mapper
)
void Foam::Cloud<ParticleType>::autoMap(const mapPolyMesh& mapper)
{
if (cloud::debug)
if (!globalPositionsPtr_.valid())
{
InfoInFunction << "for lagrangian cloud " << cloud::name() << endl;
FatalErrorInFunction
<< "Global positions are not available. "
<< "Cloud::storeGlobalPositions has not been called."
<< exit(FatalError);
}
const labelList& reverseCellMap = mapper.reverseCellMap();
const labelList& reverseFaceMap = mapper.reverseFaceMap();
// Reset stored data that relies on the mesh
// polyMesh_.clearCellTree();
cellWallFacesPtr_.clear();
@ -417,51 +415,13 @@ void Foam::Cloud<ParticleType>::autoMap
// there is a comms mismatch.
polyMesh_.tetBasePtIs();
const vectorField& positions = globalPositionsPtr_();
forAllIter(typename Cloud<ParticleType>, *this, pIter)
label i = 0;
forAllIter(typename Cloud<ParticleType>, *this, iter)
{
ParticleType& p = pIter();
if (reverseCellMap[p.cell()] >= 0)
{
p.cell() = reverseCellMap[p.cell()];
if (p.face() >= 0 && reverseFaceMap[p.face()] >= 0)
{
p.face() = reverseFaceMap[p.face()];
}
else
{
p.face() = -1;
}
p.initCellFacePt();
}
else
{
label trackStartCell = mapper.mergedCell(p.cell());
if (trackStartCell < 0)
{
trackStartCell = 0;
p.cell() = 0;
}
else
{
p.cell() = trackStartCell;
}
vector pos = p.position();
const_cast<vector&>(p.position()) =
polyMesh_.cellCentres()[trackStartCell];
p.stepFraction() = 0;
p.initCellFacePt();
p.track(pos, td);
}
iter().autoMap(positions[i], mapper);
++ i;
}
}
@ -485,6 +445,27 @@ void Foam::Cloud<ParticleType>::writePositions() const
}
template<class ParticleType>
void Foam::Cloud<ParticleType>::storeGlobalPositions() const
{
// Store the global positions for later use by autoMap. It would be
// preferable not to need this. If the mapPolyMesh object passed to autoMap
// had a copy of the old mesh then the global positions could be recovered
// within autoMap, and this pre-processing would not be necessary.
globalPositionsPtr_.reset(new vectorField(this->size()));
vectorField& positions = globalPositionsPtr_();
label i = 0;
forAllConstIter(typename Cloud<ParticleType>, *this, iter)
{
positions[i] = iter().position();
++ i;
}
}
// * * * * * * * * * * * * * * * * IOStream operators * * * * * * * * * * * //
#include "CloudIO.C"

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -87,6 +87,9 @@ class Cloud
//- Does the cell have wall faces
mutable autoPtr<PackedBoolList> cellWallFacesPtr_;
//- Temporary storage for the global particle positions
mutable autoPtr<vectorField> globalPositionsPtr_;
// Private Member Functions
@ -162,7 +165,7 @@ public:
return IDLList<ParticleType>::size();
};
DynamicList<label>& labels()
DynamicList<label>& labels() const
{
return labels_;
}
@ -256,8 +259,7 @@ public:
//- Remap the cells of particles corresponding to the
// mesh topology change
template<class TrackData>
void autoMap(TrackData& td, const mapPolyMesh&);
void autoMap(const mapPolyMesh&);
// Read
@ -304,6 +306,10 @@ public:
//- Write positions to \<cloudName\>_positions.obj file
void writePositions() const;
//- Call this before a topology change. Stores the particles global
// positions in the database for use during mapping.
void storeGlobalPositions() const;
// Ostream Operator

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -132,13 +132,6 @@ void Foam::Cloud<ParticleType>::initCloud(const bool checkClass)
// them, otherwise, if some processors have no particles then
// there is a comms mismatch.
polyMesh_.tetBasePtIs();
forAllIter(typename Cloud<ParticleType>, *this, pIter)
{
ParticleType& p = pIter();
p.initCellFacePt();
}
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -965,14 +965,7 @@ void Foam::InteractionLists<ParticleType>::prepareParticleToBeReferred
globalTransforms.transformIndex(ciat)
);
particle->position() = transform.invTransformPosition(particle->position());
particle->transformProperties(-transform.t());
if (transform.hasR())
{
particle->transformProperties(transform.R().T());
}
particle->prepareForInteractionListReferral(transform);
}
@ -1230,6 +1223,15 @@ void Foam::InteractionLists<ParticleType>::receiveReferredData
}
}
forAll(referredParticles_, refCelli)
{
IDLList<ParticleType>& refCell = referredParticles_[refCelli];
forAllIter(typename IDLList<ParticleType>, refCell, iter)
{
iter().correctAfterInteractionListReferral(ril_[refCelli][0]);
}
}
fillReferredParticleCloud();
wallFaceMap().receive(pBufs, referredWallData_);

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -65,27 +65,14 @@ public:
indexedParticle
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
const label index = 0
)
:
particle(mesh, position, celli, tetFacei, tetPti),
index_(index)
{}
//- Construct from components, with searching for tetFace and tetPt
indexedParticle
(
const polyMesh& mesh,
const vector& position,
const label celli,
const label index = 0
)
:
particle(mesh, position, celli),
particle(mesh, coordinates, celli, tetFacei, tetPti),
index_(index)
{}

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -33,6 +33,8 @@ Description
#define particle_H
#include "vector.H"
#include "barycentric.H"
#include "barycentricTensor.H"
#include "Cloud.H"
#include "IDLList.H"
#include "pointField.H"
@ -42,6 +44,7 @@ Description
#include "FixedList.H"
#include "polyMeshTetDecomposition.H"
#include "particleMacros.H"
#include "vectorTensorTransform.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -130,25 +133,19 @@ public:
};
protected:
private:
// Protected data
// Private data
//- Reference to the polyMesh database
const polyMesh& mesh_;
//- Position of particle
vector position_;
//- Coordinates of particle
barycentric coordinates_;
//- Index of the cell it is in
label celli_;
//- Face index if the particle is on a face otherwise -1
label facei_;
//- Fraction of time-step completed
scalar stepFraction_;
//- Index of the face that owns the decomposed tet that the
// particle is in
label tetFacei_;
@ -158,6 +155,12 @@ protected:
// point.
label tetPti_;
//- Face index if the particle is on a face otherwise -1
label facei_;
//- Fraction of time-step completed
scalar stepFraction_;
//- Originating processor id
label origProc_;
@ -165,74 +168,137 @@ protected:
label origId_;
private:
// Private Member Functions
//- Find the tet tri faces between position and tet centre
void findTris
// Tetrahedra functions
//- Get indices into the current face for the face-bound vertices of
// the current tet.
void tetFaceIndices
(
label& baseI,
label& vertex1I,
label& vertex2I
) const;
//- Get indices into the mesh points for the face-bound vertices of
// the current tet.
void tetMeshIndices
(
label& baseI,
label& vertex1I,
label& vertex2I
) const;
//- Get the vertices of the current tet
void tetGeometry
(
vector& centre,
vector& base,
vector& vertex1,
vector& vertex2
) const;
//- Get the transformation associated with the current tet. This
// will convert a barycentric position within the tet to a
// cartesian position in the global coordinate system. The
// conversion is x = A & y, where x is the cartesian position, y is
// the barycentric position and A is the transformation tensor.
barycentricTensor tetTransform() const;
//- Get the reverse transform associated with the current tet. The
// conversion is detA*y = (x - centre) & T. The variables x, y and
// centre have the same meaning as for the forward transform. T is
// the transposed inverse of the forward transform tensor, A,
// multiplied by its determinant, detA. This separation allows
// the barycentric tracking algorithm to function on inverted or
// degenerate tetrahedra.
void tetReverseTransform
(
vector& centre,
scalar& detA,
barycentricTensor& T
) const;
//- Get the vertices of the current moving tet. Two values are
// returned for each vertex. The first is a constant, and the
// second is a linear coefficient of the track fraction.
void movingTetGeometry
(
const scalar endStepFraction,
Pair<vector>& centre,
Pair<vector>& base,
Pair<vector>& vertex1,
Pair<vector>& vertex2
) const;
//- Get the transformation associated with the current, moving, tet.
// This is of the same form as for the static case. As with the
// moving geometry, a linear function of the tracking fraction is
// returned for each component.
Pair<barycentricTensor> movingTetTransform
(
const scalar endStepFraction
) const;
//- Get the reverse transformation associated with the current,
// moving, tet. This is of the same form as for the static case. As
// with the moving geometry, a function of the tracking fraction is
// returned for each component. The functions are higher order than
// for the forward transform; the determinant is cubic, and the
// tensor is quadratic.
void movingTetReverseTransform
(
const scalar endStepFraction,
Pair<vector>& centre,
FixedList<scalar, 4>& detA,
FixedList<barycentricTensor, 3>& T
) const;
// Transformations
//- Reflection transform. Corrects the coordinates when the particle
// moves between two tets which share a base vertex, but for which
// the other two non cell-centre vertices are reversed. All hits
// which retain the same face behave this way, as do face hits.
void reflect();
//- Rotation transform. Corrects the coordinates when the particle
// moves between two tets with different base vertices, but are
// otherwise similarly oriented. Hits which change the face within
// the cell make use of both this and the reflect transform.
void rotate(const bool direction);
// Topology changes
//- Change tet within a cell. Called after a triangle is hit.
void changeTet(const label tetTriI);
//- Change tet face within a cell. Called by changeTet.
void changeFace(const label tetTriI);
//- Change cell. Called when the particle hits an internal face.
void changeCell();
// Geometry changes
//- Locate the particle at the given position
void locate
(
const vector& position,
DynamicList<label>& faceList,
const tetPointRef& tet,
const FixedList<vector, 4>& tetAreas,
const FixedList<label, 4>& tetPlaneBasePtIs,
const scalar tol
) 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& to,
const label triI,
const vector& tetArea,
const label tetPlaneBasePtI,
const vector* direction,
const label celli,
const label tetFacei,
const label tetPti,
const scalar tol
) const;
//- Find the lambda value for a moving tri face
inline scalar movingTetLambda
(
const vector& from,
const vector& to,
const label triI,
const vector& tetArea,
const label tetPlaneBasePtI,
const label celli,
const label tetFacei,
const label tetPti,
const scalar tol
) const;
//- Modify the tet owner data by crossing triI
inline void tetNeighbour(label triI);
//- Cross the from the given face across the given edge of the
// given cell to find the resulting face and tetPti
inline void crossEdgeConnectedFace
(
const label& celli,
label& tetFacei,
label& tetPti,
const edge& e
const bool boundaryFail,
const string boundaryMsg
);
//- Hit wall faces in the current cell if the
//- wallImpactDistance is non-zero. They may not be in
//- Different tets to the current.
template<class CloudType>
inline void hitWallFaces
(
const CloudType& td,
const vector& from,
const vector& to,
scalar& lambdaMin,
tetIndices& closestTetIs
);
protected:
// Patch interactions
@ -315,8 +381,8 @@ public:
//- String representation of properties
DefinePropertyList
(
"(Px Py Pz) celli facei stepFraction "
"tetFacei tetPti origProc origId"
"(Px Py Pz) celli tetFacei tetPti "
"facei stepFraction origProc origId"
);
//- String representation of property types
@ -328,17 +394,6 @@ public:
//- Cumulative particle counter - used to provode unique ID
static label particleCount_;
//- Fraction of distance to tet centre to move a particle to
// 'rescue' it from a tracking problem
static const scalar trackingCorrectionTol;
//- Fraction of the cell volume to use in determining tolerance values
// for the denominator and numerator of lambda
static const scalar lambdaDistanceToleranceCoeff;
//- Minimum stepFraction tolerance
static const scalar minStepFractionTol;
// Constructors
@ -346,20 +401,19 @@ public:
particle
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
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
//- Construct from a position and a cell, searching for the rest of the
// required topology
particle
(
const polyMesh& mesh,
const vector& position,
const label celli,
bool doCellFacePt = true
const label celli
);
//- Construct from Istream
@ -412,27 +466,15 @@ public:
//- Return the mesh database
inline const polyMesh& mesh() const;
//- Return current particle position
inline const vector& position() const;
//- Return current particle position
inline vector& position();
//- Return current cell particle is in
inline label& cell();
//- Return current particle coordinates
inline const barycentric& coordinates() const;
//- Return current cell particle is in
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;
@ -453,43 +495,32 @@ public:
// on oldPoints
inline vector oldNormal() const;
//- Return current face particle is on otherwise -1
inline label& face();
//- Return current face particle is on otherwise -1
inline label face() const;
//- Return the impact model to be used, soft or hard (default).
inline bool softImpact() const;
//- Return the particle current time
inline scalar currentTime() const;
// Check
//- Check the stored cell value (setting if necessary) and
// initialise the tetFace and tetPt values
inline void initCellFacePt();
//- Is the particle on a face?
inline bool onFace() const;
//- Is the particle on the boundary/(or outside the domain)?
inline bool onBoundary() const;
//- Is the particle on an internal face?
inline bool onInternalFace() const;
//- Is this global face an internal face?
inline bool internalFace(const label facei) const;
//- Is the particle on a boundary face?
inline bool onBoundaryFace() const;
//- Is this global face a boundary face?
inline bool boundaryFace(const label facei) const;
//- Which patch is particle on
//- Which patch is particle on // <-- !!!
inline label patch(const label facei) const;
//- Which face of this patch is this particle on
inline label patchFace
(
const label patchi,
const label facei
) const;
//- Which face of this patch is this particle on // <-- !!!
inline label patchFace(const label patchi, const label facei) const;
//- Return current particle position
inline vector position() const;
//- Return the fraction of time-step completed
inline scalar& stepFraction();
@ -512,28 +543,57 @@ public:
// Track
//- Track particle to end of trajectory
// or until it hits the boundary.
// On entry 'stepFraction()' should be set to the fraction of the
// time-step at which the tracking starts and on exit it contains
// the fraction of the time-step completed.
// Returns the boundary face index if the track stops at the
// boundary, -1 otherwise.
template<class TrackData>
label track(const vector& endPosition, TrackData& td);
//- Track along the displacement for a given fraction of the overall
// step. End when the track is complete, or when a boundary is hit.
// On exit, stepFraction_ will have been incremented to the current
// position, and facei_ will be set to the index of the boundary
// face that was hit, or -1 if the track completed within a cell.
// The proportion of the displacement still to be completed is
// returned.
scalar track
(
const vector& displacement,
const scalar fraction
);
//- Track particle to a given position and returns 1.0 if the
// trajectory is completed without hitting a face otherwise
// stops at the face and returns the fraction of the trajectory
// completed.
// on entry 'stepFraction()' should be set to the fraction of the
// time-step at which the tracking starts.
template<class TrackData>
scalar trackToFace(const vector& endPosition, TrackData& td);
//- As particle::track, but also stops on internal faces.
scalar trackToFace
(
const vector& displacement,
const scalar fraction
);
//- Return the index of the face to be used in the interpolation
// routine
inline label faceInterpolation() const;
//- As particle::trackToFace, but also stops on tet triangles. On
// exit, tetTriI is set to the index of the tet triangle that was
// hit, or -1 if the end position was reached.
scalar trackToStationaryTri
(
const vector& displacement,
const scalar fraction,
label& tetTriI
);
//- As particle::trackToTri, but for moving meshes
scalar trackToMovingTri
(
const vector& displacement,
const scalar fraction,
label& tetTriI
);
//- As non-templated particle::trackToFace, but with additional
// boundary handling.
template<class TrackData>
void trackToFace
(
const vector& displacement,
const scalar fraction,
TrackData& td
);
//- Set the constrained components of the particle position to the
// mesh centre.
void constrainToMeshCentre();
// Transformations
@ -564,6 +624,38 @@ public:
void correctAfterParallelTransfer(const label patchi, TrackData& td);
// Interaction list referral
//- Break the topology and store the particle position so that the
// particle can be referred.
void prepareForInteractionListReferral
(
const vectorTensorTransform& transform
);
//- Correct the topology after referral. The particle may still be
// outside the stored tet and therefore not track-able.
void correctAfterInteractionListReferral(const label celli);
// Decompose and reconstruct
//- Return the tet point approproate for decomposition or reconstruction
// to or from the given mesh.
label procTetPt
(
const polyMesh& procMesh,
const label procCell,
const label procTetFace
) const;
// Mapping
//- Map after a topology change
void autoMap(const vector& position, const mapPolyMesh& mapper);
// I-O
//- Read the fields associated with the owner cloud

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -26,541 +26,6 @@ License
#include "polyMesh.H"
#include "Time.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
inline void Foam::particle::findTris
(
const vector& position,
DynamicList<label>& faceList,
const tetPointRef& tet,
const FixedList<vector, 4>& tetAreas,
const FixedList<label, 4>& tetPlaneBasePtIs,
const scalar tol
) const
{
faceList.clear();
const point Ct = tet.centre();
for (label i = 0; i < 4; i++)
{
scalar lambda = tetLambda
(
Ct,
position,
i,
tetAreas[i],
tetPlaneBasePtIs[i],
celli_,
tetFacei_,
tetPti_,
tol
);
if ((lambda > 0.0) && (lambda < 1.0))
{
faceList.append(i);
}
}
}
inline Foam::scalar Foam::particle::tetLambda
(
const vector& from,
const vector& to,
const label triI,
const vector& n,
const label tetPlaneBasePtI,
const label celli,
const label tetFacei,
const label tetPti,
const scalar tol
) const
{
const pointField& pPts = mesh_.points();
if (mesh_.moving())
{
return movingTetLambda
(
from,
to,
triI,
n,
tetPlaneBasePtI,
celli,
tetFacei,
tetPti,
tol
);
}
const point& base = pPts[tetPlaneBasePtI];
scalar lambdaNumerator = (base - from) & n;
scalar lambdaDenominator = (to - from) & n;
// n carries the area of the tet faces, so the dot product with a
// delta-length has the units of volume. Comparing the component of each
// delta-length in the direction of n times the face area to a fraction of
// the cell volume.
if (mag(lambdaDenominator) < tol)
{
if (mag(lambdaNumerator) < tol)
{
// Track starts on the face, and is potentially
// parallel to it. +-tol/+-tol is not a good
// comparison, return 0.0, in anticipation of tet
// centre correction.
return 0.0;
}
else
{
if (mag((to - from)) < tol/mag(n))
{
// 'Zero' length track (compared to the tolerance, which is
// based on the cell volume, divided by the tet face area), not
// along the face, face cannot be crossed.
return GREAT;
}
else
{
// Trajectory is non-zero and parallel to face
lambdaDenominator = sign(lambdaDenominator)*SMALL;
}
}
}
return lambdaNumerator/lambdaDenominator;
}
inline Foam::scalar Foam::particle::movingTetLambda
(
const vector& from,
const vector& to,
const label triI,
const vector& n,
const label tetPlaneBasePtI,
const label celli,
const label tetFacei,
const label tetPti,
const scalar tol
) const
{
const pointField& pPts = mesh_.points();
const pointField& oldPPts = mesh_.oldPoints();
// Base point of plane at end of motion
const point& b = pPts[tetPlaneBasePtI];
// n: Normal of plane at end of motion
// Base point of plane at start of timestep
const point& b00 = oldPPts[tetPlaneBasePtI];
// Base point of plane at start of tracking portion (cast forward by
// stepFraction)
point b0 = b00 + stepFraction_*(b - b00);
// Normal of plane at start of tracking portion
vector n0 = Zero;
{
tetIndices tetIs(celli, tetFacei, tetPti, mesh_);
// Tet at timestep start
tetPointRef tet00 = tetIs.oldTet(mesh_);
// Tet at timestep end
tetPointRef tet = tetIs.tet(mesh_);
point tet0PtA = tet00.a() + stepFraction_*(tet.a() - tet00.a());
point tet0PtB = tet00.b() + stepFraction_*(tet.b() - tet00.b());
point tet0PtC = tet00.c() + stepFraction_*(tet.c() - tet00.c());
point tet0PtD = tet00.d() + stepFraction_*(tet.d() - tet00.d());
// Tracking portion start tet (cast forward by stepFraction)
tetPointRef tet0(tet0PtA, tet0PtB, tet0PtC, tet0PtD);
switch (triI)
{
case 0:
{
n0 = tet0.Sa();
break;
}
case 1:
{
n0 = tet0.Sb();
break;
}
case 2:
{
n0 = tet0.Sc();
break;
}
case 3:
{
n0 = tet0.Sd();
break;
}
default:
{
break;
}
}
}
if (mag(n0) < SMALL)
{
// If the old normal is zero (for example in layer addition)
// then use the current normal;
n0 = n;
}
scalar lambdaNumerator = 0;
scalar lambdaDenominator = 0;
vector dP = to - from;
vector dN = n - n0;
vector dB = b - b0;
vector dS = from - b0;
if (mag(dN) > SMALL)
{
scalar a = (dP - dB) & dN;
scalar b = ((dP - dB) & n0) + (dS & dN);
scalar c = dS & n0;
if (mag(a) > SMALL)
{
// Solve quadratic for lambda
scalar discriminant = sqr(b) - 4.0*a*c;
if (discriminant < 0)
{
// Imaginary roots only - face not crossed
return GREAT;
}
else
{
scalar q = -0.5*(b + sign(b)*Foam::sqrt(discriminant));
if (mag(q) < VSMALL)
{
// If q is zero, then l1 = q/a is the required
// value of lambda, and is zero.
return 0.0;
}
scalar l1 = q/a;
scalar l2 = c/q;
// There will be two roots, a big one and a little
// one, choose the little one.
if (mag(l1) < mag(l2))
{
return l1;
}
else
{
return l2;
}
}
}
{
// When a is zero, solve the first order polynomial
lambdaNumerator = -c;
lambdaDenominator = b;
}
}
else
{
// When n = n0 is zero, there is no plane rotation, solve the
// first order polynomial
lambdaNumerator = -(dS & n0);
lambdaDenominator = ((dP - dB) & n0);
}
if (mag(lambdaDenominator) < tol)
{
if (mag(lambdaNumerator) < tol)
{
// Track starts on the face, and is potentially
// parallel to it. +-tol)/+-tol is not a good
// comparison, return 0.0, in anticipation of tet
// centre correction.
return 0.0;
}
else
{
if (mag((to - from)) < tol/mag(n))
{
// Zero length track, not along the face, face
// cannot be crossed.
return GREAT;
}
else
{
// Trajectory is non-zero and parallel to face
lambdaDenominator = sign(lambdaDenominator)*SMALL;
}
}
}
return lambdaNumerator/lambdaDenominator;
}
inline void Foam::particle::tetNeighbour(label triI)
{
const labelList& pOwner = mesh_.faceOwner();
const faceList& pFaces = mesh_.faces();
bool own = (pOwner[tetFacei_] == celli_);
const Foam::face& f = pFaces[tetFacei_];
label tetBasePtI = mesh_.tetBasePtIs()[tetFacei_];
if (tetBasePtI == -1)
{
FatalErrorInFunction
<< "No base point for face " << tetFacei_ << ", " << f
<< ", produces a valid tet decomposition."
<< abort(FatalError);
}
label facePtI = (tetPti_ + tetBasePtI) % f.size();
label otherFacePtI = f.fcIndex(facePtI);
switch (triI)
{
case 0:
{
// Crossing this triangle changes tet to that in the
// neighbour cell over tetFacei
// Modification of celli_ will happen by other indexing,
// tetFacei_ and tetPti don't change.
break;
}
case 1:
{
crossEdgeConnectedFace
(
celli_,
tetFacei_,
tetPti_,
Foam::edge(f[facePtI], f[otherFacePtI])
);
break;
}
case 2:
{
if (own)
{
if (tetPti_ < f.size() - 2)
{
tetPti_ = f.fcIndex(tetPti_);
}
else
{
crossEdgeConnectedFace
(
celli_,
tetFacei_,
tetPti_,
Foam::edge(f[tetBasePtI], f[otherFacePtI])
);
}
}
else
{
if (tetPti_ > 1)
{
tetPti_ = f.rcIndex(tetPti_);
}
else
{
crossEdgeConnectedFace
(
celli_,
tetFacei_,
tetPti_,
Foam::edge(f[tetBasePtI], f[facePtI])
);
}
}
break;
}
case 3:
{
if (own)
{
if (tetPti_ > 1)
{
tetPti_ = f.rcIndex(tetPti_);
}
else
{
crossEdgeConnectedFace
(
celli_,
tetFacei_,
tetPti_,
Foam::edge(f[tetBasePtI], f[facePtI])
);
}
}
else
{
if (tetPti_ < f.size() - 2)
{
tetPti_ = f.fcIndex(tetPti_);
}
else
{
crossEdgeConnectedFace
(
celli_,
tetFacei_,
tetPti_,
Foam::edge(f[tetBasePtI], f[otherFacePtI])
);
}
}
break;
}
default:
{
FatalErrorInFunction
<< "Tet tri face index error, can only be 0..3, supplied "
<< triI << abort(FatalError);
break;
}
}
}
inline void Foam::particle::crossEdgeConnectedFace
(
const label& celli,
label& tetFacei,
label& tetPti,
const edge& e
)
{
const faceList& pFaces = mesh_.faces();
const cellList& pCells = mesh_.cells();
const Foam::face& f = pFaces[tetFacei];
const Foam::cell& thisCell = pCells[celli];
forAll(thisCell, cFI)
{
// Loop over all other faces of this cell and
// find the one that shares this edge
label fI = thisCell[cFI];
if (tetFacei == fI)
{
continue;
}
const Foam::face& otherFace = pFaces[fI];
label edDir = otherFace.edgeDirection(e);
if (edDir == 0)
{
continue;
}
else if (f == pFaces[fI])
{
// This is a necessary condition if using duplicate baffles
// (so coincident faces). We need to make sure we don't cross into
// the face with the same vertices since we might enter a tracking
// loop where it never exits. This test should be cheap
// for most meshes so can be left in for 'normal' meshes.
continue;
}
else
{
//Found edge on other face
tetFacei = fI;
label eIndex = -1;
if (edDir == 1)
{
// Edge is in the forward circulation of this face, so
// work with the start point of the edge
eIndex = findIndex(otherFace, e.start());
}
else
{
// edDir == -1, so the edge is in the reverse
// circulation of this face, so work with the end
// point of the edge
eIndex = findIndex(otherFace, e.end());
}
label tetBasePtI = mesh_.tetBasePtIs()[fI];
if (tetBasePtI == -1)
{
FatalErrorInFunction
<< "No base point for face " << fI << ", " << f
<< ", produces a decomposition that has a minimum "
<< "volume greater than tolerance."
<< abort(FatalError);
}
// Find eIndex relative to the base point on new face
eIndex -= tetBasePtI;
if (neg(eIndex))
{
eIndex = (eIndex + otherFace.size()) % otherFace.size();
}
if (eIndex == 0)
{
// The point is the base point, so this is first tet
// in the face circulation
tetPti = 1;
}
else if (eIndex == otherFace.size() - 1)
{
// The point is the last before the base point, so
// this is the last tet in the face circulation
tetPti = otherFace.size() - 2;
}
else
{
tetPti = eIndex;
}
break;
}
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline Foam::label Foam::particle::getNewParticleID() const
@ -583,15 +48,9 @@ inline const Foam::polyMesh& Foam::particle::mesh() const
}
inline const Foam::vector& Foam::particle::position() const
inline const Foam::barycentric& Foam::particle::coordinates() const
{
return position_;
}
inline Foam::vector& Foam::particle::position()
{
return position_;
return coordinates_;
}
@ -601,36 +60,18 @@ inline Foam::label Foam::particle::cell() const
}
inline Foam::label& Foam::particle::cell()
{
return celli_;
}
inline Foam::label Foam::particle::tetFace() const
{
return tetFacei_;
}
inline Foam::label& Foam::particle::tetFace()
{
return tetFacei_;
}
inline Foam::label Foam::particle::tetPt() const
{
return tetPti_;
}
inline Foam::label& Foam::particle::tetPt()
{
return tetPti_;
}
inline Foam::tetIndices Foam::particle::currentTetIndices() const
{
return tetIndices(celli_, tetFacei_, tetPti_, mesh_);
@ -661,158 +102,34 @@ inline Foam::label Foam::particle::face() const
}
inline Foam::label& Foam::particle::face()
inline bool Foam::particle::onFace() const
{
return facei_;
return facei_ >= 0;
}
inline void Foam::particle::initCellFacePt()
inline bool Foam::particle::onInternalFace() const
{
if (celli_ == -1)
{
mesh_.findCellFacePt
(
position_,
celli_,
tetFacei_,
tetPti_
);
return onFace() && mesh_.isInternalFace(facei_);
}
if (debug && celli_ == -1)
inline bool Foam::particle::onBoundaryFace() const
{
return onFace() && !mesh_.isInternalFace(facei_);
}
inline Foam::vector Foam::particle::position() const
{
if (mesh_.moving())
{
WarningInFunction
<< "cell, tetFace and tetPt search failure for position "
<< position_
<< endl;
}
return movingTetTransform(0)[0] & coordinates_;
}
else
{
mesh_.findTetFacePt(celli_, position_, tetFacei_, tetPti_);
if (tetFacei_ == -1 || tetPti_ == -1)
{
label oldCelli = celli_;
mesh_.findCellFacePt
(
position_,
celli_,
tetFacei_,
tetPti_
);
if (celli_ == -1 || tetFacei_ == -1 || tetPti_ == -1)
{
// The particle has entered this function with a cell number,
// but hasn't been able to find a cell to occupy.
if (!mesh_.pointInCellBB(position_, oldCelli, 0.1))
{
// If the position is not inside the (slightly extended)
// bound-box of the cell that it thought it should be in,
// then this is considered an error.
if (debug)
{
WarningInFunction
<< "position " << position_
<< " not in specified cell " << oldCelli
<< " with centre " << mesh_.cellCentres()[oldCelli]
<< endl;
return tetTransform() & coordinates_;
}
celli_ = -1;
tetFacei_ = -1;
tetPti_ = -1;
return;
}
// The position is in the (slightly extended) bound-box of the
// cell. This situation may arise because the face
// decomposition of the cell is not the same as when the
// particle acquired the cell index. For example, it has been
// read into a mesh that has made a different face base-point
// decision for a boundary face and now this particle is in a
// position that is not in the mesh. Gradually move the
// particle towards the centre of the cell that it thought that
// it was in.
celli_ = oldCelli;
point newPosition = position_;
const point& cC = mesh_.cellCentres()[celli_];
label trap(1.0/trackingCorrectionTol + 1);
label iterNo = 0;
do
{
newPosition += trackingCorrectionTol*(cC - position_);
mesh_.findTetFacePt
(
celli_,
newPosition,
tetFacei_,
tetPti_
);
iterNo++;
} while (tetFacei_ < 0 && iterNo <= trap);
if (tetFacei_ == -1)
{
FatalErrorInFunction
<< "cell, tetFace and tetPt search failure at position "
<< position_ << abort(FatalError);
}
if (debug)
{
WarningInFunction
<< "Particle moved from " << position_
<< " to " << newPosition
<< " in cell " << celli_
<< " tetFace " << tetFacei_
<< " tetPt " << tetPti_ << nl
<< " (A fraction of "
<< 1.0 - mag(cC - newPosition)/mag(cC - position_)
<< " of the distance to the cell centre)"
<< " because a decomposition tetFace and tetPt "
<< "could not be found."
<< endl;
}
position_ = newPosition;
}
if (debug && celli_ != oldCelli)
{
WarningInFunction
<< "Particle at position " << position_
<< " searched for a cell, tetFace and tetPt." << nl
<< " Found"
<< " cell " << celli_
<< " tetFace " << tetFacei_
<< " tetPt " << tetPti_ << nl
<< " This is a different cell to that which was supplied"
<< " (" << oldCelli << ")." << nl
<< endl;
}
}
}
}
inline bool Foam::particle::onBoundary() const
{
return facei_ != -1 && facei_ >= mesh_.nInternalFaces();
}
@ -852,29 +169,9 @@ inline Foam::label& Foam::particle::origId()
}
inline bool Foam::particle::softImpact() const
{
return false;
}
inline Foam::scalar Foam::particle::currentTime() const
{
return
mesh_.time().value()
+ stepFraction_*mesh_.time().deltaTValue();
}
inline bool Foam::particle::internalFace(const label facei) const
{
return mesh_.isInternalFace(facei);
}
bool Foam::particle::boundaryFace(const label facei) const
{
return !internalFace(facei);
return mesh_.time().value() + stepFraction_*mesh_.time().deltaTValue();
}
@ -894,10 +191,4 @@ inline Foam::label Foam::particle::patchFace
}
inline Foam::label Foam::particle::faceInterpolation() const
{
return facei_;
}
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -33,12 +33,12 @@ Foam::string Foam::particle::propertyTypes_ = Foam::particle::propertyTypes();
const std::size_t Foam::particle::sizeofPosition_
(
offsetof(particle, facei_) - offsetof(particle, position_)
offsetof(particle, facei_) - offsetof(particle, coordinates_)
);
const std::size_t Foam::particle::sizeofFields
(
sizeof(particle) - offsetof(particle, position_)
sizeof(particle) - offsetof(particle, coordinates_)
);
@ -47,38 +47,33 @@ const std::size_t Foam::particle::sizeofFields
Foam::particle::particle(const polyMesh& mesh, Istream& is, bool readFields)
:
mesh_(mesh),
position_(),
coordinates_(),
celli_(-1),
facei_(-1),
stepFraction_(0.0),
tetFacei_(-1),
tetPti_(-1),
facei_(-1),
stepFraction_(0.0),
origProc_(Pstream::myProcNo()),
origId_(-1)
{
if (is.format() == IOstream::ASCII)
{
is >> position_ >> celli_;
is >> coordinates_ >> celli_ >> tetFacei_ >> tetPti_;
if (readFields)
{
is >> facei_
>> stepFraction_
>> tetFacei_
>> tetPti_
>> origProc_
>> origId_;
is >> facei_ >> stepFraction_ >> origProc_ >> origId_;
}
}
else
{
if (readFields)
{
is.read(reinterpret_cast<char*>(&position_), sizeofFields);
is.read(reinterpret_cast<char*>(&coordinates_), sizeofFields_);
}
else
{
is.read(reinterpret_cast<char*>(&position_), sizeofPosition_);
is.read(reinterpret_cast<char*>(&coordinates_), sizeofPosition_);
}
}
@ -91,11 +86,14 @@ void Foam::particle::writePosition(Ostream& os) const
{
if (os.format() == IOstream::ASCII)
{
os << position_ << token::SPACE << celli_;
os << coordinates_
<< token::SPACE << celli_
<< token::SPACE << tetFacei_
<< token::SPACE << tetPti_;
}
else
{
os.write(reinterpret_cast<const char*>(&position_), sizeofPosition_);
os.write(reinterpret_cast<const char*>(&coordinates_), sizeofPosition_);
}
// Check state of Ostream
@ -107,12 +105,12 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const particle& p)
{
if (os.format() == IOstream::ASCII)
{
os << p.position_
os << p.coordinates_
<< token::SPACE << p.celli_
<< token::SPACE << p.facei_
<< token::SPACE << p.stepFraction_
<< token::SPACE << p.tetFacei_
<< token::SPACE << p.tetPti_
<< token::SPACE << p.facei_
<< token::SPACE << p.stepFraction_
<< token::SPACE << p.origProc_
<< token::SPACE << p.origId_;
}
@ -120,8 +118,8 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const particle& p)
{
os.write
(
reinterpret_cast<const char*>(&p.position_),
particle::sizeofFields
reinterpret_cast<const char*>(&p.coordinates_),
particle::sizeofFields_
);
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -44,7 +44,7 @@ void Foam::particle::prepareForParallelTransfer
)
{
// Convert the face index to be local to the processor patch
facei_ = patchFace(patchi, facei_);
facei_ = mesh_.boundaryMesh()[patchi].whichFace(facei_);
}
@ -58,12 +58,6 @@ void Foam::particle::correctAfterParallelTransfer
const coupledPolyPatch& ppp =
refCast<const coupledPolyPatch>(mesh_.boundaryMesh()[patchi]);
celli_ = ppp.faceCells()[facei_];
// Have patch transform the position
ppp.transformPosition(position_, facei_);
// Transform the properties
if (!ppp.parallel())
{
const tensor& T =
@ -85,41 +79,22 @@ void Foam::particle::correctAfterParallelTransfer
transformProperties(-s);
}
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.
// Set the topology
celli_ = ppp.faceCells()[facei_];
facei_ += ppp.start();
tetFacei_ = facei_;
// Faces either side of a coupled patch are numbered in opposite directions
// as their normals both point away from their connected cells. The tet
// point therefore counts in the opposite direction from the base point.
tetPti_ = mesh_.faces()[tetFacei_].size() - 1 - tetPti_;
// Reset the face index for the next tracking operation
if (stepFraction_ > (1.0 - SMALL))
{
stepFraction_ = 1.0;
facei_ = -1;
}
else
{
facei_ += ppp.start();
}
// Reflect to account for the change of triangle orientation in the new cell
reflect();
// Note that the position does not need transforming explicitly. The face-
// triangle on the receive patch is the transformation of the one on the
// send patch, so whilst the barycentric coordinates remain the same, the
// change of triangle implicitly transforms the position.
}
@ -158,7 +133,6 @@ void Foam::particle::readFields(CloudType& c)
template<class CloudType>
void Foam::particle::writeFields(const CloudType& c)
{
// Write the cloud position file
IOPosition<CloudType> ioP(c);
ioP.write();
@ -169,7 +143,11 @@ void Foam::particle::writeFields(const CloudType& c)
c.fieldIOobject("origProcId", IOobject::NO_READ),
np
);
IOField<label> origId(c.fieldIOobject("origId", IOobject::NO_READ), np);
IOField<label> origId
(
c.fieldIOobject("origId", IOobject::NO_READ),
np
);
label i = 0;
forAllConstIter(typename CloudType, c, iter)
@ -208,378 +186,46 @@ void Foam::particle::writeObjects(const CloudType& c, objectRegistry& obr)
template<class TrackData>
Foam::label Foam::particle::track(const vector& endPosition, TrackData& td)
{
facei_ = -1;
// Tracks to endPosition or stop on boundary
while (!onBoundary() && stepFraction_ < 1.0 - SMALL)
{
stepFraction_ += trackToFace(endPosition, td)*(1.0 - stepFraction_);
}
return facei_;
}
template<class TrackData>
Foam::scalar Foam::particle::trackToFace
void Foam::particle::trackToFace
(
const vector& endPosition,
const vector& displacement,
const scalar fraction,
TrackData& td
)
{
typedef typename TrackData::cloudType cloudType;
typedef typename cloudType::particleType particleType;
// Track
trackToFace(displacement, fraction);
cloudType& cloud = td.cloud();
const faceList& pFaces = mesh_.faces();
const pointField& pPts = mesh_.points();
const vectorField& pC = mesh_.cellCentres();
facei_ = -1;
// Pout<< "Particle " << origId_ << " " << origProc_
// << " Tracking from " << position_
// << " to " << endPosition
// << endl;
// Pout<< "stepFraction " << stepFraction_ << nl
// << "celli " << celli_ << nl
// << "tetFacei " << tetFacei_ << nl
// << "tetPti " << tetPti_
// << endl;
scalar trackFraction = 0.0;
// Minimum tetrahedron decomposition of each cell of the mesh into
// using the cell centre, base point on face, and further two
// points on the face. For each face of n points, there are n - 2
// tets generated.
// 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;
// What tolerance is appropriate the minimum lambda numerator and
// denominator for tracking in this cell.
scalar lambdaDistanceTolerance =
lambdaDistanceToleranceCoeff*mesh_.cellVolumes()[celli_];
do
// If the track is complete, return
if (!onFace())
{
if (triI != -1)
{
// Change tet ownership because a tri face has been crossed
tetNeighbour(triI);
return;
}
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
{
fPtAI = otherFacePtI;
fPtBI = facePtI;
}
tetPointRef tet
(
pC[celli_],
pPts[basePtI],
pPts[f[fPtAI]],
pPts[f[fPtBI]]
);
if (lambdaMin < SMALL)
{
// Apply tracking correction towards tet centre
if (debug)
{
Pout<< "tracking rescue using tetCentre from " << position();
}
position_ += trackingCorrectionTol*(tet.centre() - position_);
if (debug)
{
Pout<< " to " << position() << " due to "
<< (tet.centre() - position_) << endl;
}
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,
lambdaDistanceTolerance
);
// Reset variables for new track
triI = -1;
lambdaMin = VGREAT;
// Pout<< "tris " << tris << endl;
// Sets a value for lambdaMin and facei_ if a wall face is hit
// by the track.
hitWallFaces
(
cloud,
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,
tI,
tetAreas[tI],
tetPlaneBasePtIs[tI],
celli_,
tetFacei_,
tetPti_,
lambdaDistanceTolerance
);
if (lam < lambdaMin)
{
lambdaMin = lam;
triI = tI;
}
}
}
if (triI == 0)
{
// This must be a cell face crossing
facei_ = tetFacei_;
// Set the faceHitTetIs to those for the current tet in case a
// wall interaction is required with the cell face
faceHitTetIs = tetIndices
(
celli_,
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;
}
// Pout<< "track loop " << position_ << " " << endPosition << nl
// << " " << celli_
// << " " << facei_
// << " " << tetFacei_
// << " " << tetPti_
// << " " << triI
// << " " << lambdaMin
// << " " << trackFraction
// << endl;
// Pout<< "# Tracking loop tet "
// << origId_ << " " << origProc_<< nl
// << "# face: " << tetFacei_ << nl
// << "# tetPti: " << tetPti_ << nl
// << "# tetBasePtI: " << mesh_.tetBasePtIs()[tetFacei_] << nl
// << "# tet.mag(): " << tet.mag() << nl
// << "# tet.quality(): " << tet.quality()
// << endl;
// meshTools::writeOBJ(Pout, tet.a());
// meshTools::writeOBJ(Pout, tet.b());
// meshTools::writeOBJ(Pout, tet.c());
// meshTools::writeOBJ(Pout, tet.d());
// Pout<< "f 1 3 2" << nl
// << "f 2 3 4" << nl
// << "f 1 4 3" << nl
// << "f 1 2 4" << endl;
// 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)
{
trackFraction += lambdaMin*(1 - trackFraction);
position_ += lambdaMin*(endPosition - position_);
}
else
{
position_ = endPosition;
return 1.0;
}
}
else
{
// Set lambdaMin to zero to force a towards-tet-centre
// correction.
lambdaMin = 0.0;
}
} while (facei_ < 0);
// Hit face/patch processing
typedef typename TrackData::cloudType::particleType particleType;
particleType& p = static_cast<particleType&>(*this);
p.hitFace(td);
if (internalFace(facei_))
if (onInternalFace())
{
// 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_];
}
else if (celli_ == mesh_.faceNeighbour()[facei_])
{
celli_ = mesh_.faceOwner()[facei_];
}
else
{
FatalErrorInFunction
<< "addressing failure" << abort(FatalError);
}
changeCell();
}
else
{
label origFacei = facei_;
label patchi = patch(facei_);
label patchi = mesh_.boundaryMesh().whichPatch(facei_);
// No action taken for tetPti_ for tetFacei_ here, handled by
// patch interaction call or later during processor transfer.
// No action is taken for tetPti_ for tetFacei_ here. These are handled
// by the patch interaction call or later during processor transfer.
const tetIndices faceHitTetIs =
polyMeshTetDecomposition::triangleTetIndices
(
mesh_,
tetFacei_,
celli_,
tetPti_
);
if
(
@ -588,7 +234,7 @@ Foam::scalar Foam::particle::trackToFace
mesh_.boundaryMesh()[patchi],
td,
patchi,
trackFraction,
stepFraction(),
faceHitTetIs
)
)
@ -596,7 +242,7 @@ Foam::scalar Foam::particle::trackToFace
// Did patch interaction model switch patches?
if (facei_ != origFacei)
{
patchi = patch(facei_);
patchi = mesh_.boundaryMesh().whichPatch(facei_);
}
const polyPatch& patch = mesh_.boundaryMesh()[patchi];
@ -635,7 +281,7 @@ Foam::scalar Foam::particle::trackToFace
(
static_cast<const cyclicAMIPolyPatch&>(patch),
td,
endPosition - position_
displacement
);
}
else if (isA<processorPolyPatch>(patch))
@ -658,290 +304,6 @@ Foam::scalar Foam::particle::trackToFace
}
}
}
if (lambdaMin < SMALL)
{
// Apply tracking correction towards tet centre.
// Generate current tet to find centre to apply correction.
tetPointRef tet = currentTet();
if (debug)
{
Pout<< "tracking rescue for lambdaMin:" << lambdaMin
<< "from " << position();
}
position_ += trackingCorrectionTol*(tet.centre() - position_);
if
(
cloud.hasWallImpactDistance()
&& !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 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_ +=
trackingCorrectionTol
*(
(wallTet.centre() - (position_ + r*nHat))
- (nHat & (tet.centre() - position_))*nHat
);
}
}
if (debug)
{
Pout<< " to " << position() << endl;
}
cloud.trackingRescue();
}
return trackFraction;
}
template<class CloudType>
void Foam::particle::hitWallFaces
(
const CloudType& cloud,
const vector& from,
const vector& to,
scalar& lambdaMin,
tetIndices& closestTetIs
)
{
typedef typename CloudType::particleType particleType;
if (!(cloud.hasWallImpactDistance() && cloud.cellHasWallFaces()[celli_]))
{
return;
}
particleType& p = static_cast<particleType&>(*this);
const faceList& pFaces = mesh_.faces();
const Foam::cell& thisCell = mesh_.cells()[celli_];
scalar lambdaDistanceTolerance =
lambdaDistanceToleranceCoeff*mesh_.cellVolumes()[celli_];
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
forAll(thisCell, cFI)
{
label fI = thisCell[cFI];
if (internalFace(fI))
{
continue;
}
label patchi = patches.patchID()[fI - mesh_.nInternalFaces()];
if (isA<wallPolyPatch>(patches[patchi]))
{
// Get the decomposition of this wall face
const List<tetIndices> faceTetIs =
polyMeshTetDecomposition::faceTetIndices(mesh_, fI, celli_);
const Foam::face& f = pFaces[fI];
forAll(faceTetIs, tI)
{
const tetIndices& tetIs = faceTetIs[tI];
triPointRef tri = tetIs.faceTri(mesh_);
vector n = tri.normal();
vector nHat = n/mag(n);
// Radius of particle with respect to this wall face
// triangle. Assuming that the wallImpactDistance
// does not change as the particle or the mesh moves
// forward in time.
scalar r = p.wallImpactDistance(nHat);
vector toPlusRNHat = to + r*nHat;
// triI = 0 because it is the cell face tri of the tet
// we are concerned with.
scalar tetClambda = tetLambda
(
tetIs.tet(mesh_).centre(),
toPlusRNHat,
0,
n,
f[tetIs.faceBasePt()],
celli_,
fI,
tetIs.tetPt(),
lambdaDistanceTolerance
);
if ((tetClambda <= 0.0) || (tetClambda >= 1.0))
{
// toPlusRNHat is not on the outside of the plane of
// the wall face tri, the tri cannot be hit.
continue;
}
// Check if the actual trajectory of the near-tri
// points intersects the triangle.
vector fromPlusRNHat = from + r*nHat;
// triI = 0 because it is the cell face tri of the tet
// we are concerned with.
scalar lambda = tetLambda
(
fromPlusRNHat,
toPlusRNHat,
0,
n,
f[tetIs.faceBasePt()],
celli_,
fI,
tetIs.tetPt(),
lambdaDistanceTolerance
);
pointHit hitInfo(Zero);
if (mesh_.moving())
{
// For a moving mesh, the position of wall
// triangle needs to be moved in time to be
// consistent with the moment defined by the
// current value of stepFraction and the value of
// lambda just calculated.
// Total fraction thought the timestep of the
// motion, including stepFraction before the
// current tracking step and the current
// lambda
// i.e.
// let s = stepFraction, l = lambda
// Motion of x in time:
// |-----------------|---------|---------|
// x00 x0 xi x
//
// where xi is the correct value of x at the required
// tracking instant.
//
// x0 = x00 + s*(x - x00) = s*x + (1 - s)*x00
//
// i.e. the motion covered by previous tracking portions
// within this timestep, and
//
// xi = x0 + l*(x - x0)
// = l*x + (1 - l)*x0
// = l*x + (1 - l)*(s*x + (1 - s)*x00)
// = (s + l - s*l)*x + (1 - (s + l - s*l))*x00
//
// let m = (s + l - s*l)
//
// xi = m*x + (1 - m)*x00 = x00 + m*(x - x00);
//
// In the same form as before.
// Clip lambda to 0.0-1.0 to ensure that sensible
// positions are used for triangle intersections.
scalar lam = max(0.0, min(1.0, lambda));
scalar m = stepFraction_ + lam - (stepFraction_*lam);
triPointRef tri00 = tetIs.oldFaceTri(mesh_);
// Use SMALL positive tolerance to make the triangle
// slightly "fat" to improve robustness. Intersection
// is calculated as the ray (from + r*nHat) -> (to +
// r*nHat).
point tPtA = tri00.a() + m*(tri.a() - tri00.a());
point tPtB = tri00.b() + m*(tri.b() - tri00.b());
point tPtC = tri00.c() + m*(tri.c() - tri00.c());
triPointRef t(tPtA, tPtB, tPtC);
// The point fromPlusRNHat + m*(to - from) is on the
// plane of the triangle. Determine the
// intersection with this triangle by testing if
// this point is inside or outside of the triangle.
hitInfo = t.intersection
(
fromPlusRNHat + m*(to - from),
t.normal(),
intersection::FULL_RAY,
SMALL
);
}
else
{
// Use SMALL positive tolerance to make the triangle
// slightly "fat" to improve robustness. Intersection
// is calculated as the ray (from + r*nHat) -> (to +
// r*nHat).
hitInfo = tri.intersection
(
fromPlusRNHat,
(to - from),
intersection::FULL_RAY,
SMALL
);
}
if (hitInfo.hit())
{
if (lambda < lambdaMin)
{
lambdaMin = lambda;
facei_ = fI;
closestTetIs = tetIs;
}
}
}
}
}
}
@ -1017,22 +379,17 @@ void Foam::particle::hitCyclicPatch
TrackData& td
)
{
facei_ = cpp.transformGlobalFace(facei_);
const cyclicPolyPatch& receiveCpp = cpp.neighbPatch();
const label receiveFacei = receiveCpp.whichFace(facei_);
// Set the topology
facei_ = tetFacei_ = cpp.transformGlobalFace(facei_);
celli_ = mesh_.faceOwner()[facei_];
tetFacei_ = facei_;
// See note in correctAfterParallelTransfer for tetPti_ addressing.
// See note in correctAfterParallelTransfer for tetPti addressing ...
tetPti_ = mesh_.faces()[tetFacei_].size() - 1 - tetPti_;
const cyclicPolyPatch& receiveCpp = cpp.neighbPatch();
label patchFacei = receiveCpp.whichFace(facei_);
// Now the particle is on the receiving side
// Have patch transform the position
receiveCpp.transformPosition(position_, patchFacei);
// Reflect to account for the change of triangle orientation in the new cell
reflect();
// Transform the properties
if (!receiveCpp.parallel())
@ -1041,7 +398,7 @@ void Foam::particle::hitCyclicPatch
(
receiveCpp.forwardT().size() == 1
? receiveCpp.forwardT()[0]
: receiveCpp.forwardT()[patchFacei]
: receiveCpp.forwardT()[receiveFacei]
);
transformProperties(T);
}
@ -1051,7 +408,7 @@ void Foam::particle::hitCyclicPatch
(
(receiveCpp.separation().size() == 1)
? receiveCpp.separation()[0]
: receiveCpp.separation()[patchFacei]
: receiveCpp.separation()[receiveFacei]
);
transformProperties(-s);
}
@ -1066,38 +423,41 @@ void Foam::particle::hitCyclicAMIPatch
const vector& direction
)
{
vector pos = position();
const cyclicAMIPolyPatch& receiveCpp = cpp.neighbPatch();
const label sendFacei = cpp.whichFace(facei_);
const label receiveFacei = cpp.pointFace(sendFacei, direction, pos);
// Patch face index on sending side
label patchFacei = facei_ - cpp.start();
// Patch face index on receiving side - also updates position
patchFacei = cpp.pointFace(patchFacei, direction, position_);
if (patchFacei < 0)
if (receiveFacei < 0)
{
// If the patch face of the particle is not known assume that
// the particle is lost and to be deleted
// If the patch face of the particle is not known assume that the
// particle is lost and mark it to be deleted.
td.keepParticle = false;
WarningInFunction
<< "Particle lost across " << cyclicAMIPolyPatch::typeName
<< " patches " << cpp.name() << " and " << receiveCpp.name()
<< " at position " << position_
<< endl;
<< " at position " << pos << endl;
}
// Convert face index into global numbering
facei_ = patchFacei + receiveCpp.start();
// Set the topology
facei_ = tetFacei_ = receiveFacei + receiveCpp.start();
celli_ = mesh_.faceOwner()[facei_];
// Locate the particle on the recieving side
locate
(
pos,
&direction,
mesh_.faceOwner()[facei_],
false,
"Particle crossed between " + cyclicAMIPolyPatch::typeName +
" patches " + cpp.name() + " and " + receiveCpp.name() +
" to a location outside of the mesh."
);
tetFacei_ = facei_;
// See note in correctAfterParallelTransfer for tetPti_ addressing.
tetPti_ = mesh_.faces()[tetFacei_].size() - 1 - tetPti_;
// Now the particle is on the receiving side
// The particle must remain associated with a face for the tracking to
// register as incomplete
facei_ = tetFacei_;
// Transform the properties
if (!receiveCpp.parallel())
@ -1106,7 +466,7 @@ void Foam::particle::hitCyclicAMIPatch
(
receiveCpp.forwardT().size() == 1
? receiveCpp.forwardT()[0]
: receiveCpp.forwardT()[patchFacei]
: receiveCpp.forwardT()[receiveFacei]
);
transformProperties(T);
}
@ -1116,7 +476,7 @@ void Foam::particle::hitCyclicAMIPatch
(
(receiveCpp.separation().size() == 1)
? receiveCpp.separation()[0]
: receiveCpp.separation()[patchFacei]
: receiveCpp.separation()[receiveFacei]
);
transformProperties(-s);
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -61,26 +61,26 @@ public:
passiveParticle
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
)
:
particle(mesh, position, celli, tetFacei, tetPti)
particle(mesh, coordinates, celli, tetFacei, tetPti)
{}
//- Construct from components, with searching for tetFace and
// tetPt unless disabled by doCellFacePt = false.
//- Construct from a position and a cell, searching for the rest of the
// required topology
passiveParticle
(
const polyMesh& mesh,
const vector& position,
const label celli,
bool doCellFacePt = true
const label celli
)
:
particle(mesh, position, celli, doCellFacePt)
particle(mesh, position, celli)
{}
//- Construct from Istream

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -318,7 +318,7 @@ Foam::KinematicCloud<CloudType>::KinematicCloud
),
rndGen_(Pstream::myProcNo()),
cellOccupancyPtr_(),
cellLengthScale_(cbrt(mesh_.V())),
cellLengthScale_(mag(cbrt(mesh_.V()))),
rho_(rho),
U_(U),
mu_(mu),
@ -845,18 +845,14 @@ void Foam::KinematicCloud<CloudType>::updateMesh()
{
updateCellOccupancy();
injectors_.updateMesh();
cellLengthScale_ = cbrt(mesh_.V());
cellLengthScale_ = mag(cbrt(mesh_.V()));
}
template<class CloudType>
void Foam::KinematicCloud<CloudType>::autoMap(const mapPolyMesh& mapper)
{
typedef typename particle::TrackingData<KinematicCloud<CloudType>> tdType;
tdType td(*this);
Cloud<parcelType>::template autoMap<tdType>(td, mapper);
Cloud<parcelType>::autoMap(mapper);
updateMesh();
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -333,11 +333,7 @@ void Foam::ReactingCloud<CloudType>::evolve()
template<class CloudType>
void Foam::ReactingCloud<CloudType>::autoMap(const mapPolyMesh& mapper)
{
typedef typename particle::TrackingData<ReactingCloud<CloudType>> tdType;
tdType td(*this);
Cloud<parcelType>::template autoMap<tdType>(td, mapper);
Cloud<parcelType>::autoMap(mapper);
this->updateMesh();
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -259,12 +259,7 @@ void Foam::ReactingMultiphaseCloud<CloudType>::autoMap
const mapPolyMesh& mapper
)
{
typedef typename particle::TrackingData<ReactingMultiphaseCloud<CloudType>>
tdType;
tdType td(*this);
Cloud<parcelType>::template autoMap<tdType>(td, mapper);
Cloud<parcelType>::autoMap(mapper);
this->updateMesh();
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -480,11 +480,7 @@ void Foam::ThermoCloud<CloudType>::evolve()
template<class CloudType>
void Foam::ThermoCloud<CloudType>::autoMap(const mapPolyMesh& mapper)
{
typedef typename particle::TrackingData<ThermoCloud<CloudType>> tdType;
tdType td(*this);
Cloud<parcelType>::template autoMap<tdType>(td, mapper);
Cloud<parcelType>::autoMap(mapper);
this->updateMesh();
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -172,22 +172,31 @@ public:
// Constructors
//- Construct from owner, position, and cloud owner
//- Construct from mesh, coordinates and topology
// Other properties initialised as null
inline CollidingParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
);
//- Construct from a position and a cell, searching for the rest of the
// required topology. Other properties are initialised as null.
inline CollidingParcel
(
const polyMesh& mesh,
const vector& position,
const label celli
);
//- Construct from components
inline CollidingParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -63,13 +63,13 @@ template<class ParcelType>
inline Foam::CollidingParcel<ParcelType>::CollidingParcel
(
const polyMesh& owner,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
)
:
ParcelType(owner, position, celli, tetFacei, tetPti),
ParcelType(owner, coordinates, celli, tetFacei, tetPti),
f_(Zero),
angularMomentum_(Zero),
torque_(Zero),
@ -82,6 +82,22 @@ inline Foam::CollidingParcel<ParcelType>::CollidingParcel
(
const polyMesh& owner,
const vector& position,
const label celli
)
:
ParcelType(owner, position, celli),
f_(Zero),
angularMomentum_(Zero),
torque_(Zero),
collisionRecords_()
{}
template<class ParcelType>
inline Foam::CollidingParcel<ParcelType>::CollidingParcel
(
const polyMesh& owner,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -99,7 +115,7 @@ inline Foam::CollidingParcel<ParcelType>::CollidingParcel
ParcelType
(
owner,
position,
coordinates,
celli,
tetFacei,
tetPti,

View File

@ -268,71 +268,50 @@ bool Foam::KinematicParcel<ParcelType>::move
const cloudSolution& solution = td.cloud().solution();
const scalarField& cellLengthScale = td.cloud().cellLengthScale();
scalar tEnd = (1.0 - p.stepFraction())*trackTime;
scalar dtMax = solution.deltaTMax(trackTime);
bool tracking = true;
label nTrackingStalled = 0;
while (td.keepParticle && !td.switchProcessor && tEnd > ROOTVSMALL)
while (td.keepParticle && !td.switchProcessor && p.stepFraction() < 1)
{
// Apply correction to position for reduced-D cases
meshTools::constrainToMeshCentre(mesh, p.position());
p.constrainToMeshCentre();
const point start(p.position());
// Set the Lagrangian time-step
scalar dt = min(dtMax, tEnd);
// Cache the parcel current cell as this will change if a face is hit
// Cache the current position, cell and step-fraction
const point start = p.position();
const label celli = p.cell();
const scalar sfrac = p.stepFraction();
const scalar magU = mag(U_);
if (p.active() && tracking && (magU > ROOTVSMALL))
// Total displacement over the time-step
const vector s = trackTime*U_;
// Cell length scale
const scalar l = cellLengthScale[p.cell()];
// Fraction of the displacement to track in this loop. This is limited
// to ensure that the both the time and distance tracked is less than
// maxCo times the total value.
scalar f = 1 - p.stepFraction();
f = min(f, maxCo);
f = min(f, maxCo*l/max(SMALL*l, mag(s)));
if (p.active())
{
const scalar d = dt*magU;
const scalar deltaLMax = solution.deltaLMax(cellLengthScale[celli]);
const scalar dCorr = min(d, deltaLMax);
dt *=
dCorr/d
*p.trackToFace(p.position() + dCorr*U_/magU, td);
}
tEnd -= dt;
const scalar newStepFraction = 1.0 - tEnd/trackTime;
if (tracking)
{
if
(
mag(p.stepFraction() - newStepFraction)
< particle::minStepFractionTol
)
{
nTrackingStalled++;
if (nTrackingStalled > maxTrackAttempts)
{
tracking = false;
}
// Track to the next face
p.trackToFace(f*s, f, td);
}
else
{
nTrackingStalled = 0;
}
}
p.stepFraction() = newStepFraction;
bool calcParcel = true;
if (!tracking && solution.steadyState())
// Abandon the track, and move to the end of the sub-step. If the
// the mesh is moving, this will implicitly move the parcel.
if (mesh.moving())
{
calcParcel = false;
WarningInFunction
<< "Tracking was abandoned on a moving mesh. Parcels may "
<< "move unphysically as a result." << endl;
}
p.stepFraction() += f;
}
const scalar dt = (p.stepFraction() - sfrac)*trackTime;
// Avoid problems with extremely small timesteps
if ((dt > ROOTVSMALL) && calcParcel)
if (!td.cloud().solution().steadyState() && dt > ROOTVSMALL)
{
// Update cell based properties
p.setCellValues(td, dt, celli);
@ -345,7 +324,7 @@ bool Foam::KinematicParcel<ParcelType>::move
p.calc(td, dt, celli);
}
if (p.onBoundary() && td.keepParticle)
if (p.onBoundaryFace() && td.keepParticle)
{
if (isA<processorPolyPatch>(pbMesh[p.patch(p.face())]))
{

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -340,22 +340,31 @@ public:
// Constructors
//- Construct from owner, position, and cloud owner
//- Construct from mesh, coordinates and topology
// Other properties initialised as null
inline KinematicParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
);
//- Construct from a position and a cell, searching for the rest of the
// required topology. Other properties are initialised as null.
inline KinematicParcel
(
const polyMesh& mesh,
const vector& position,
const label celli
);
//- Construct from components
inline KinematicParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -495,9 +504,6 @@ public:
// Helper functions
//- Return the index of the face used in the interpolation routine
inline label faceInterpolation() const;
//- Cell owner mass
inline scalar massCell(const label celli) const;

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -73,13 +73,13 @@ template<class ParcelType>
inline Foam::KinematicParcel<ParcelType>::KinematicParcel
(
const polyMesh& owner,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
)
:
ParcelType(owner, position, celli, tetFacei, tetPti),
ParcelType(owner, coordinates, celli, tetFacei, tetPti),
active_(true),
typeId_(-1),
nParticle_(0),
@ -101,6 +101,31 @@ inline Foam::KinematicParcel<ParcelType>::KinematicParcel
(
const polyMesh& owner,
const vector& position,
const label celli
)
:
ParcelType(owner, position, celli),
active_(true),
typeId_(-1),
nParticle_(0),
d_(0.0),
dTarget_(0.0),
U_(Zero),
rho_(0.0),
age_(0.0),
tTurb_(0.0),
UTurb_(Zero),
rhoc_(0.0),
Uc_(Zero),
muc_(0.0)
{}
template<class ParcelType>
inline Foam::KinematicParcel<ParcelType>::KinematicParcel
(
const polyMesh& owner,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -112,7 +137,7 @@ inline Foam::KinematicParcel<ParcelType>::KinematicParcel
const constantProperties& constProps
)
:
ParcelType(owner, position, celli, tetFacei, tetPti),
ParcelType(owner, coordinates, celli, tetFacei, tetPti),
active_(true),
typeId_(typeId),
nParticle_(nParticle0),
@ -334,21 +359,6 @@ inline Foam::vector& Foam::KinematicParcel<ParcelType>::UTurb()
}
template<class ParcelType>
inline Foam::label Foam::KinematicParcel<ParcelType>::faceInterpolation() const
{
// Use volume-based interpolation if dealing with external faces
if (this->cloud().internalFace(this->face()))
{
return this->face();
}
else
{
return -1;
}
}
template<class ParcelType>
inline Foam::scalar Foam::KinematicParcel<ParcelType>::massCell
(

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2013-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2013-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -190,22 +190,31 @@ public:
// Constructors
//- Construct from owner, position, and cloud owner
//- Construct from mesh, coordinates and topology
// Other properties initialised as null
inline MPPICParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
);
//- Construct from a position and a cell, searching for the rest of the
// required topology. Other properties are initialised as null.
inline MPPICParcel
(
const polyMesh& mesh,
const vector& position,
const label celli
);
//- Construct from components
inline MPPICParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2013-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2013-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -29,13 +29,13 @@ template<class ParcelType>
inline Foam::MPPICParcel<ParcelType>::MPPICParcel
(
const polyMesh& owner,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
)
:
ParcelType(owner, position, celli, tetFacei, tetPti),
ParcelType(owner, coordinates, celli, tetFacei, tetPti),
UCorrect_(Zero)
{}
@ -45,6 +45,19 @@ inline Foam::MPPICParcel<ParcelType>::MPPICParcel
(
const polyMesh& owner,
const vector& position,
const label celli
)
:
ParcelType(owner, position, celli),
UCorrect_(Zero)
{}
template<class ParcelType>
inline Foam::MPPICParcel<ParcelType>::MPPICParcel
(
const polyMesh& owner,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -60,7 +73,7 @@ inline Foam::MPPICParcel<ParcelType>::MPPICParcel
ParcelType
(
owner,
position,
coordinates,
celli,
tetFacei,
tetPti,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -278,23 +278,31 @@ public:
// Constructors
//- Construct from owner, position, and cloud owner
//- Construct from mesh, position and topology
// Other properties initialised as null
inline ReactingMultiphaseParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
);
//- Construct from a position and a cell, searching for the rest of the
// required topology. Other properties are initialised as null.
inline ReactingMultiphaseParcel
(
const polyMesh& mesh,
const vector& position,
const label celli
);
//- Construct from components
inline ReactingMultiphaseParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -68,13 +68,13 @@ template<class ParcelType>
inline Foam::ReactingMultiphaseParcel<ParcelType>::ReactingMultiphaseParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
)
:
ParcelType(mesh, position, celli, tetFacei, tetPti),
ParcelType(mesh, coordinates, celli, tetFacei, tetPti),
YGas_(0),
YLiquid_(0),
YSolid_(0),
@ -87,6 +87,22 @@ inline Foam::ReactingMultiphaseParcel<ParcelType>::ReactingMultiphaseParcel
(
const polyMesh& mesh,
const vector& position,
const label celli
)
:
ParcelType(mesh, position, celli),
YGas_(0),
YLiquid_(0),
YSolid_(0),
canCombust_(0)
{}
template<class ParcelType>
inline Foam::ReactingMultiphaseParcel<ParcelType>::ReactingMultiphaseParcel
(
const polyMesh& mesh,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -108,7 +124,7 @@ inline Foam::ReactingMultiphaseParcel<ParcelType>::ReactingMultiphaseParcel
ParcelType
(
mesh,
position,
coordinates,
celli,
tetFacei,
tetPti,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -232,22 +232,31 @@ public:
// Constructors
//- Construct from owner, position, and cloud owner
//- Construct from mesh, coordinates and topology
// Other properties initialised as null
inline ReactingParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
);
//- Construct from a position and a cell, searching for the rest of the
// required topology. Other properties are initialised as null.
inline ReactingParcel
(
const polyMesh& mesh,
const vector& position,
const label celli
);
//- Construct from components
inline ReactingParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -63,13 +63,13 @@ template<class ParcelType>
inline Foam::ReactingParcel<ParcelType>::ReactingParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
)
:
ParcelType(mesh, position, celli, tetFacei, tetPti),
ParcelType(mesh, coordinates, celli, tetFacei, tetPti),
mass0_(0.0),
Y_(0),
pc_(0.0)
@ -81,6 +81,21 @@ inline Foam::ReactingParcel<ParcelType>::ReactingParcel
(
const polyMesh& mesh,
const vector& position,
const label celli
)
:
ParcelType(mesh, position, celli),
mass0_(0.0),
Y_(0),
pc_(0.0)
{}
template<class ParcelType>
inline Foam::ReactingParcel<ParcelType>::ReactingParcel
(
const polyMesh& mesh,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -99,7 +114,7 @@ inline Foam::ReactingParcel<ParcelType>::ReactingParcel
ParcelType
(
mesh,
position,
coordinates,
celli,
tetFacei,
tetPti,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -288,22 +288,31 @@ public:
// Constructors
//- Construct from owner, position, and cloud owner
//- Construct from mesh, coordinates and topology
// Other properties initialised as null
inline ThermoParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
);
//- Construct from a position and a cell, searching for the rest of the
// required topology. Other properties are initialised as null.
inline ThermoParcel
(
const polyMesh& mesh,
const vector& position,
const label celli
);
//- Construct from components
inline ThermoParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -74,13 +74,13 @@ template<class ParcelType>
inline Foam::ThermoParcel<ParcelType>::ThermoParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
)
:
ParcelType(mesh, position, celli, tetFacei, tetPti),
ParcelType(mesh, coordinates, celli, tetFacei, tetPti),
T_(0.0),
Cp_(0.0),
Tc_(0.0),
@ -93,6 +93,22 @@ inline Foam::ThermoParcel<ParcelType>::ThermoParcel
(
const polyMesh& mesh,
const vector& position,
const label celli
)
:
ParcelType(mesh, position, celli),
T_(0.0),
Cp_(0.0),
Tc_(0.0),
Cpc_(0.0)
{}
template<class ParcelType>
inline Foam::ThermoParcel<ParcelType>::ThermoParcel
(
const polyMesh& mesh,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -110,7 +126,7 @@ inline Foam::ThermoParcel<ParcelType>::ThermoParcel
ParcelType
(
mesh,
position,
coordinates,
celli,
tetFacei,
tetPti,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -485,8 +485,7 @@ void Foam::InjectionModel<CloudType>::inject(TrackData& td)
meshTools::constrainToMeshCentre(mesh, pos);
// Create a new parcel
parcelType* pPtr =
new parcelType(mesh, pos, celli, tetFacei, tetPti);
parcelType* pPtr = new parcelType(mesh, pos, celli);
// Check/set new parcel thermo properties
cloud.setParcelThermoProperties(*pPtr, dt);
@ -610,8 +609,7 @@ void Foam::InjectionModel<CloudType>::injectSteadyState
meshTools::constrainToMeshCentre(mesh, pos);
// Create a new parcel
parcelType* pPtr =
new parcelType(mesh, pos, celli, tetFacei, tetPti);
parcelType* pPtr = new parcelType(mesh, pos, celli);
// Check/set new parcel thermo properties
cloud.setParcelThermoProperties(*pPtr, 0.0);

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -146,16 +146,6 @@ void Foam::SurfaceFilmModel<CloudType>::inject(TrackData& td)
{
const label celli = injectorCellsPatch[j];
// The position could bein any tet of the decomposed cell,
// so arbitrarily choose the first face of the cell as the
// tetFace and the first point on the face after the base
// point as the tetPt. The tracking will pick the cell
// consistent with the motion in the first tracking step.
const label tetFacei = this->owner().mesh().cells()[celli][0];
const label tetPti = 1;
// const point& pos = this->owner().mesh().C()[celli];
const scalar offset =
max
(
@ -166,14 +156,7 @@ void Foam::SurfaceFilmModel<CloudType>::inject(TrackData& td)
// Create a new parcel
parcelType* pPtr =
new parcelType
(
this->owner().pMesh(),
pos,
celli,
tetFacei,
tetPti
);
new parcelType(this->owner().pMesh(), pos, celli);
// Check/set new parcel thermo properties
td.cloud().setParcelThermoProperties(*pPtr, 0.0);

View File

@ -446,7 +446,7 @@ void Foam::ThermoSurfaceFilm<CloudType>::splashInteraction
}
// Perturb new parcels towards the owner cell centre
pPtr->position() += 0.5*rndGen_.sample01<scalar>()*(posC - posCf);
pPtr->track(0.5*rndGen_.sample01<scalar>()*(posC - posCf), 0);
pPtr->nParticle() = npNew[i];

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -85,18 +85,10 @@ bool Foam::molecule::move(molecule::trackingData& td, const scalar trackTime)
{
// Leapfrog tracking part
scalar tEnd = (1.0 - stepFraction())*trackTime;
scalar dtMax = tEnd;
while (td.keepParticle && !td.switchProcessor && tEnd > ROOTVSMALL)
while (td.keepParticle && !td.switchProcessor && stepFraction() < 1)
{
// set the lagrangian time-step
scalar dt = min(dtMax, tEnd);
dt *= trackToFace(position() + dt*v_, td);
tEnd -= dt;
stepFraction() = 1.0 - tEnd/trackTime;
const scalar f = 1 - stepFraction();
trackToFace(f*trackTime*v_, f, td);
}
}
else if (td.part() == 2)
@ -205,7 +197,7 @@ void Foam::molecule::transformProperties(const tensor& T)
rf_ = transform(T, rf_);
sitePositions_ = position_ + (T & (sitePositions_ - position_));
sitePositions_ = position() + (T & (sitePositions_ - position()));
siteForces_ = T & siteForces_;
}
@ -226,7 +218,7 @@ void Foam::molecule::transformProperties(const vector& separation)
void Foam::molecule::setSitePositions(const constantProperties& constProps)
{
sitePositions_ = position_ + (Q_ & constProps.siteReferencePositions());
sitePositions_ = position() + (Q_ & constProps.siteReferencePositions());
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -238,7 +238,7 @@ public:
inline molecule
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -253,6 +253,24 @@ public:
const label id
);
//- Construct from a position and a cell, searching for the rest of the
// required topology
inline molecule
(
const polyMesh& mesh,
const vector& position,
const label celli,
const tensor& Q,
const vector& v,
const vector& a,
const vector& pi,
const vector& tau,
const vector& specialPosition,
const constantProperties& constProps,
const label special,
const label id
);
//- Construct from Istream
molecule
(

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -220,7 +220,7 @@ inline Foam::molecule::constantProperties::constantProperties
inline Foam::molecule::molecule
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -236,7 +236,42 @@ inline Foam::molecule::molecule
)
:
particle(mesh, position, celli, tetFacei, tetPti),
particle(mesh, coordinates, celli, tetFacei, tetPti),
Q_(Q),
v_(v),
a_(a),
pi_(pi),
tau_(tau),
specialPosition_(specialPosition),
potentialEnergy_(0.0),
rf_(Zero),
special_(special),
id_(id),
siteForces_(constProps.nSites(), Zero),
sitePositions_(constProps.nSites())
{
setSitePositions(constProps);
}
inline Foam::molecule::molecule
(
const polyMesh& mesh,
const vector& position,
const label celli,
const tensor& Q,
const vector& v,
const vector& a,
const vector& pi,
const vector& tau,
const vector& specialPosition,
const constantProperties& constProps,
const label special,
const label id
)
:
particle(mesh, position, celli),
Q_(Q),
v_(v),
a_(a),

View File

@ -746,17 +746,8 @@ void Foam::moleculeCloud::initialiseMolecules
globalPosition
);
label cell = -1;
label tetFace = -1;
label tetPt = -1;
mesh_.findCellFacePt
(
globalPosition,
cell,
tetFace,
tetPt
);
const label cell =
mesh_.cellTree().findInside(globalPosition);
if (findIndex(zone, cell) != -1)
{
@ -764,8 +755,6 @@ void Foam::moleculeCloud::initialiseMolecules
(
globalPosition,
cell,
tetFace,
tetPt,
id,
tethered,
temperature,
@ -834,16 +823,10 @@ void Foam::moleculeCloud::initialiseMolecules
globalPosition
);
label cell = -1;
label tetFace = -1;
label tetPt = -1;
mesh_.findCellFacePt
const label cell =
mesh_.cellTree().findInside
(
globalPosition,
cell,
tetFace,
tetPt
globalPosition
);
if (findIndex(zone, cell) != -1)
@ -852,8 +835,6 @@ void Foam::moleculeCloud::initialiseMolecules
(
globalPosition,
cell,
tetFace,
tetPt,
id,
tethered,
temperature,
@ -913,16 +894,10 @@ void Foam::moleculeCloud::initialiseMolecules
globalPosition
);
label cell = -1;
label tetFace = -1;
label tetPt = -1;
mesh_.findCellFacePt
const label cell =
mesh_.cellTree().findInside
(
globalPosition,
cell,
tetFace,
tetPt
globalPosition
);
if (findIndex(zone, cell) != -1)
@ -931,8 +906,6 @@ void Foam::moleculeCloud::initialiseMolecules
(
globalPosition,
cell,
tetFace,
tetPt,
id,
tethered,
temperature,
@ -996,26 +969,12 @@ void Foam::moleculeCloud::createMolecule
(
const point& position,
label cell,
label tetFace,
label tetPt,
label id,
bool tethered,
scalar temperature,
const vector& bulkVelocity
)
{
if (cell == -1)
{
mesh_.findCellFacePt(position, cell, tetFace, tetPt);
}
if (cell == -1)
{
FatalErrorInFunction
<< "Position specified does not correspond to a mesh cell." << nl
<< abort(FatalError);
}
point specialPosition(Zero);
label special = 0;
@ -1068,8 +1027,6 @@ void Foam::moleculeCloud::createMolecule
mesh_,
position,
cell,
tetFace,
tetPt,
Q,
v,
Zero,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -114,8 +114,6 @@ private:
(
const point& position,
label cell,
label tetFace,
label tetPt,
label id,
bool tethered,
scalar temperature,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -43,34 +43,27 @@ bool Foam::solidParticle::move
td.switchProcessor = false;
td.keepParticle = true;
const polyBoundaryMesh& pbMesh = mesh_.boundaryMesh();
const polyBoundaryMesh& pbMesh = mesh().boundaryMesh();
scalar tEnd = (1.0 - stepFraction())*trackTime;
scalar dtMax = tEnd;
while (td.keepParticle && !td.switchProcessor && tEnd > SMALL)
while (td.keepParticle && !td.switchProcessor && stepFraction() < 1)
{
if (debug)
{
Info<< "Time = " << mesh_.time().timeName()
Info<< "Time = " << mesh().time().timeName()
<< " trackTime = " << trackTime
<< " tEnd = " << tEnd
<< " steptFraction() = " << stepFraction() << endl;
}
// set the lagrangian time-step
scalar dt = min(dtMax, tEnd);
// remember which cell the parcel is in
// since this will change if a face is hit
label celli = cell();
const label celli = cell();
const scalar sfrac = stepFraction();
dt *= trackToFace(position() + dt*U_, td);
const scalar f = 1 - stepFraction();
trackToFace(f*trackTime*U_, f, td);
tEnd -= dt;
stepFraction() = 1.0 - tEnd/trackTime;
const scalar dt = (stepFraction() - sfrac)*trackTime;
cellPointWeight cpw(mesh_, position(), celli, face());
cellPointWeight cpw(mesh(), position(), celli, face());
scalar rhoc = td.rhoInterp().interpolate(cpw);
vector Uc = td.UInterp().interpolate(cpw);
scalar nuc = td.nuInterp().interpolate(cpw);
@ -90,7 +83,7 @@ bool Foam::solidParticle::move
U_ = (U_ + dt*(Dc*Uc + (1.0 - rhoc/rhop)*td.g()))/(1.0 + dt*Dc);
if (onBoundary() && td.keepParticle)
if (onBoundaryFace() && td.keepParticle)
{
if (isA<processorPolyPatch>(pbMesh[patch(face())]))
{
@ -133,7 +126,7 @@ void Foam::solidParticle::hitWallPatch
const tetIndices& tetIs
)
{
vector nw = tetIs.faceTri(mesh_).normal();
vector nw = tetIs.faceTri(mesh()).normal();
nw /= mag(nw);
scalar Un = U_ & nw;

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -133,7 +133,7 @@ public:
inline solidParticle
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -45,7 +45,7 @@ inline Foam::solidParticle::trackingData::trackingData
inline Foam::solidParticle::solidParticle
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -53,7 +53,7 @@ inline Foam::solidParticle::solidParticle
const vector& U
)
:
particle(mesh, position, celli, tetFacei, tetPti),
particle(mesh, coordinates, celli, tetFacei, tetPti),
d_(d),
U_(U)
{}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -219,22 +219,31 @@ public:
// Constructors
//- Construct from owner, position, and cloud owner
//- Construct from mesh, coordinates and topology
// Other properties initialised as null
inline SprayParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
);
//- Construct from a position and a cell, searching for the rest of the
// required topology. Other properties are initialised as null.
inline SprayParcel
(
const polyMesh& mesh,
const vector& position,
const label celli
);
//- Construct from components
inline SprayParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -107,15 +107,15 @@ template<class ParcelType>
inline Foam::SprayParcel<ParcelType>::SprayParcel
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti
)
:
ParcelType(mesh, position, celli, tetFacei, tetPti),
ParcelType(mesh, coordinates, celli, tetFacei, tetPti),
d0_(this->d()),
position0_(position),
position0_(this->position()),
sigma_(0.0),
mu_(0.0),
liquidCore_(0.0),
@ -135,6 +135,31 @@ inline Foam::SprayParcel<ParcelType>::SprayParcel
(
const polyMesh& mesh,
const vector& position,
const label celli
)
:
ParcelType(mesh, position, celli),
d0_(this->d()),
position0_(this->position()),
sigma_(0.0),
mu_(0.0),
liquidCore_(0.0),
KHindex_(0.0),
y_(0.0),
yDot_(0.0),
tc_(0.0),
ms_(0.0),
injector_(1.0),
tMom_(GREAT),
user_(0.0)
{}
template<class ParcelType>
inline Foam::SprayParcel<ParcelType>::SprayParcel
(
const polyMesh& mesh,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPti,
@ -162,7 +187,7 @@ inline Foam::SprayParcel<ParcelType>::SprayParcel
ParcelType
(
mesh,
position,
coordinates,
celli,
tetFacei,
tetPti,
@ -178,7 +203,7 @@ inline Foam::SprayParcel<ParcelType>::SprayParcel
constProps
),
d0_(d0),
position0_(position),
position0_(this->position()),
sigma_(constProps.sigma0()),
mu_(constProps.mu0()),
liquidCore_(liquidCore),

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
@ -350,18 +350,7 @@ void Foam::meshRefinement::markFeatureCellLevel
{
const point& keepPoint = keepPoints[i];
label cellI = -1;
label tetFaceI = -1;
label tetPtI = -1;
// Force construction of search tree even if processor holds no
// cells
(void)mesh_.cellTree();
if (mesh_.nCells())
{
mesh_.findCellFacePt(keepPoint, cellI, tetFaceI, tetPtI);
}
const label celli = mesh_.cellTree().findInside(keepPoint);
if (cellI != -1)
{
@ -404,10 +393,15 @@ void Foam::meshRefinement::markFeatureCellLevel
(
mesh_,
keepPoint,
<<<<<<< HEAD
cellI,
tetFaceI,
tetPtI,
featureMesh.points()[pointI], // endpos
=======
celli,
featureMesh.points()[pointi], // endpos
>>>>>>> 371762757... Lagrangian: Rewrite of the particle tracking algorithm to function in
featureLevel, // level
featI, // featureMesh
pointI, // end point
@ -449,10 +443,15 @@ void Foam::meshRefinement::markFeatureCellLevel
(
mesh_,
keepPoint,
<<<<<<< HEAD
cellI,
tetFaceI,
tetPtI,
featureMesh.points()[pointI], // endpos
=======
celli,
featureMesh.points()[pointi], // endpos
>>>>>>> 371762757... Lagrangian: Rewrite of the particle tracking algorithm to function in
featureLevel, // level
featI, // featureMesh
pointI, // end point
@ -545,8 +544,14 @@ void Foam::meshRefinement::markFeatureCellLevel
label otherPointI = e.otherVertex(pointI);
trackedParticle* tp(new trackedParticle(startTp));
<<<<<<< HEAD
tp->end() = featureMesh.points()[otherPointI];
tp->j() = otherPointI;
=======
tp->start() = tp->position();
tp->end() = featureMesh.points()[otherPointi];
tp->j() = otherPointi;
>>>>>>> 371762757... Lagrangian: Rewrite of the particle tracking algorithm to function in
tp->k() = edgeI;
if (debug&meshRefinement::FEATURESEEDS)
@ -605,8 +610,14 @@ void Foam::meshRefinement::markFeatureCellLevel
const edge& e = featureMesh.edges()[edgeI];
label otherPointI = e.otherVertex(pointI);
<<<<<<< HEAD
tp.end() = featureMesh.points()[otherPointI];
tp.j() = otherPointI;
=======
tp.start() = tp.position();
tp.end() = featureMesh.points()[otherPointi];
tp.j() = otherPointi;
>>>>>>> 371762757... Lagrangian: Rewrite of the particle tracking algorithm to function in
tp.k() = edgeI;
keepParticle = true;
break;

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2014 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -31,7 +31,7 @@ License
Foam::trackedParticle::trackedParticle
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPtI,
@ -42,7 +42,30 @@ Foam::trackedParticle::trackedParticle
const label k
)
:
particle(mesh, position, celli, tetFacei, tetPtI),
particle(mesh, coordinates, celli, tetFacei, tetPtI),
start_(position()),
end_(end),
level_(level),
i_(i),
j_(j),
k_(k)
{}
Foam::trackedParticle::trackedParticle
(
const polyMesh& mesh,
const vector& position,
const label celli,
const point& end,
const label level,
const label i,
const label j,
const label k
)
:
particle(mesh, position, celli),
start_(this->position()),
end_(end),
level_(level),
i_(i),
@ -64,7 +87,7 @@ Foam::trackedParticle::trackedParticle
{
if (is.format() == IOstream::ASCII)
{
is >> end_;
is >> start_ >> end_;
level_ = readLabel(is);
i_ = readLabel(is);
j_ = readLabel(is);
@ -74,8 +97,8 @@ Foam::trackedParticle::trackedParticle
{
is.read
(
reinterpret_cast<char*>(&end_),
sizeof(end_) + sizeof(level_)
reinterpret_cast<char*>(&start_),
sizeof(start_) + sizeof(end_) + sizeof(level_)
+ sizeof(i_) + sizeof(j_) + sizeof(k_)
);
}
@ -96,9 +119,8 @@ bool Foam::trackedParticle::move
td.switchProcessor = false;
scalar tEnd = (1.0 - stepFraction())*trackTime;
scalar dtMax = tEnd;
if (tEnd <= SMALL && onBoundary())
if (tEnd <= SMALL && onBoundaryFace())
{
// This is a hack to handle particles reaching their endpoint
// on a processor boundary. If the endpoint is on a processor face
@ -111,18 +133,13 @@ bool Foam::trackedParticle::move
{
td.keepParticle = true;
while (td.keepParticle && !td.switchProcessor && tEnd > SMALL)
while (td.keepParticle && !td.switchProcessor && stepFraction() < 1)
{
// set the lagrangian time-step
scalar dt = min(dtMax, tEnd);
// mark visited cell with max level.
td.maxLevel_[cell()] = max(td.maxLevel_[cell()], level_);
dt *= trackToFace(end_, td);
tEnd -= dt;
stepFraction() = 1.0 - tEnd/trackTime;
const scalar f = 1 - stepFraction();
trackToFace(f*(end_ - start_), f, td);
}
}
@ -248,6 +265,7 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const trackedParticle& p)
if (os.format() == IOstream::ASCII)
{
os << static_cast<const particle&>(p)
<< token::SPACE << p.start_
<< token::SPACE << p.end_
<< token::SPACE << p.level_
<< token::SPACE << p.i_
@ -259,8 +277,8 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const trackedParticle& p)
os << static_cast<const particle&>(p);
os.write
(
reinterpret_cast<const char*>(&p.end_),
sizeof(p.end_) + sizeof(p.level_)
reinterpret_cast<const char*>(&p.start_),
sizeof(p.start_) + sizeof(p.end_) + sizeof(p.level_)
+ sizeof(p.i_) + sizeof(p.j_) + sizeof(p.k_)
);
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -64,6 +64,9 @@ class trackedParticle
{
// Private data
//- Start point to track from
point start_;
//- End point to track to
point end_;
@ -120,7 +123,7 @@ public:
trackedParticle
(
const polyMesh& mesh,
const vector& position,
const barycentric& coordinates,
const label celli,
const label tetFacei,
const label tetPtI,
@ -131,6 +134,20 @@ public:
const label k
);
//- Construct from a position and a cell, searching for the rest of the
// required topology
trackedParticle
(
const polyMesh& mesh,
const vector& position,
const label celli,
const point& end,
const label level,
const label i,
const label j,
const label k
);
//- Construct from Istream
trackedParticle
(
@ -170,6 +187,12 @@ public:
// Member Functions
//- Point to track from
point& start()
{
return start_;
}
//- Point to track to
point& end()
{

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -48,9 +48,7 @@ void Foam::reconstructLagrangianPositions
forAll(meshes, i)
{
const labelList& cellMap = cellProcAddressing[i];
// faceProcAddressing not required currently.
// const labelList& faceMap = faceProcAddressing[i];
const labelList& faceMap = faceProcAddressing[i];
Cloud<passiveParticle> lpi(meshes[i], cloudName, false);
@ -58,18 +56,21 @@ void Foam::reconstructLagrangianPositions
{
const passiveParticle& ppi = iter();
// // Inverting sign if necessary and subtracting 1 from
// // faceProcAddressing
// label mappedTetFace = mag(faceMap[ppi.tetFace()]) - 1;
const label mappedCell = cellMap[ppi.cell()];
// Inverting sign if necessary and subtracting 1 from
// faceProcAddressing
label mappedTetFace = mag(faceMap[ppi.tetFace()]) - 1;
lagrangianPositions.append
(
new passiveParticle
(
mesh,
ppi.position(),
cellMap[ppi.cell()],
false
ppi.coordinates(),
mappedCell,
mappedTetFace,
ppi.procTetPt(mesh, mappedCell, mappedTetFace)
)
);
}

View File

@ -56,13 +56,15 @@ bool Foam::faceOnlySet::trackToBoundary
{
particle::TrackingData<passiveParticleCloud> trackData(particleCloud);
const point& trackPt = singleParticle.position();
point trackPt = singleParticle.position();
while(true)
{
point oldPoint = trackPt;
singleParticle.trackToFace(end_, trackData);
singleParticle.trackToFace(end_ - start_, 0, trackData);
trackPt = singleParticle.position();
if (singleParticle.face() != -1 && mag(oldPoint - trackPt) > smallDist)
{
@ -78,7 +80,7 @@ bool Foam::faceOnlySet::trackToBoundary
// End reached
return false;
}
else if (singleParticle.onBoundary())
else if (singleParticle.onBoundaryFace())
{
// Boundary reached
return true;

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -56,29 +56,16 @@ bool Foam::polyLineSet::trackToBoundary
{
particle::TrackingData<passiveParticleCloud> trackData(particleCloud);
// Alias
const point& trackPt = singleParticle.position();
while (true)
{
// Local geometry info
const vector offset = sampleCoords_[sampleI+1] - sampleCoords_[sampleI];
const scalar smallDist = mag(tol*offset);
point oldPos = trackPt;
label facei = -1;
do
{
singleParticle.stepFraction() = 0;
singleParticle.track(sampleCoords_[sampleI+1], trackData);
}
while
(
!singleParticle.onBoundary()
&& (mag(trackPt - oldPos) < smallDist)
);
singleParticle.track(offset, 0);
const point trackPt = singleParticle.position();
if (singleParticle.onBoundary())
if (singleParticle.onBoundaryFace())
{
//Info<< "trackToBoundary : reached boundary"
// << " trackPt:" << trackPt << endl;
@ -94,7 +81,7 @@ bool Foam::polyLineSet::trackToBoundary
// << endl;
samplingPts.append(trackPt);
samplingCells.append(singleParticle.cell());
samplingFaces.append(facei);
samplingFaces.append(singleParticle.face());
// trackPt is at sampleI+1
samplingCurveDist.append(1.0*(sampleI+1));

View File

@ -209,17 +209,25 @@ Foam::point Foam::sampledSet::pushIn
label tetPtI;
mesh().findTetFacePt(celli, facePt, tetFacei, tetPtI);
// This is the tolerance that was defined as a static constant of the
// particle class. It is no longer used by particle, following the switch to
// barycentric tracking. The only place in which the tolerance is now used
// is here. I'm not sure what the purpose of this code is, but it probably
// wants removing. It is doing tet-searches for a particle position. This
// should almost certainly be left to the particle class.
const scalar trackingCorrectionTol = 1e-5;
if (tetFacei == -1 || tetPtI == -1)
{
newPosition = facePt;
label trap(1.0/particle::trackingCorrectionTol + 1);
label trap(1.0/trackingCorrectionTol + 1);
label iterNo = 0;
do
{
newPosition += particle::trackingCorrectionTol*(cC - facePt);
newPosition += trackingCorrectionTol*(cC - facePt);
mesh().findTetFacePt
(

View File

@ -94,8 +94,7 @@ bool Foam::uniformSet::trackToBoundary
const vector smallVec = tol*offset;
const scalar smallDist = mag(smallVec);
// Alias
const point& trackPt = singleParticle.position();
point trackPt = singleParticle.position();
particle::TrackingData<passiveParticleCloud> trackData(particleCloud);
@ -153,32 +152,10 @@ bool Foam::uniformSet::trackToBoundary
<< " to:" << samplePt << endl;
}
point oldPos = trackPt;
label facei = -1;
do
{
singleParticle.stepFraction() = 0;
singleParticle.track(samplePt, trackData);
singleParticle.track(samplePt - trackPt, 0);
trackPt = singleParticle.position();
if (debug)
{
Pout<< "Result of tracking "
<< " trackPt:" << trackPt
<< " trackCelli:" << singleParticle.cell()
<< " trackFacei:" << singleParticle.face()
<< " onBoundary:" << singleParticle.onBoundary()
<< " samplePt:" << samplePt
<< " smallDist:" << smallDist
<< endl;
}
}
while
(
!singleParticle.onBoundary()
&& (mag(trackPt - oldPos) < smallDist)
);
if (singleParticle.onBoundary())
if (singleParticle.onBoundaryFace())
{
//Pout<< "trackToBoundary : reached boundary" << endl;
if (mag(trackPt - samplePt) < smallDist)
@ -188,7 +165,7 @@ bool Foam::uniformSet::trackToBoundary
// Reached samplePt on boundary
samplingPts.append(trackPt);
samplingCells.append(singleParticle.cell());
samplingFaces.append(facei);
samplingFaces.append(singleParticle.face());
samplingCurveDist.append(mag(trackPt - start_));
}

View File

@ -47,7 +47,6 @@ runTimeModifiable true;
functions
{
#include "streamLines"
#include "wallBoundedStreamLines"
#include "cuttingPlane"
#include "forceCoeffs"
#include "ensightWrite"