236 lines
6.8 KiB
C
236 lines
6.8 KiB
C
/*---------------------------------------------------------------------------*\
|
|
========= |
|
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
\\ / O peration |
|
|
\\ / A nd | Copyright (C) 2013-2016 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 "patchInjectionBase.H"
|
|
#include "polyMesh.H"
|
|
#include "SubField.H"
|
|
#include "cachedRandom.H"
|
|
#include "triPointRef.H"
|
|
|
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
|
|
Foam::patchInjectionBase::patchInjectionBase
|
|
(
|
|
const polyMesh& mesh,
|
|
const word& patchName
|
|
)
|
|
:
|
|
patchName_(patchName),
|
|
patchId_(mesh.boundaryMesh().findPatchID(patchName_)),
|
|
patchArea_(0.0),
|
|
patchNormal_(),
|
|
cellOwners_(),
|
|
triFace_(),
|
|
triToFace_(),
|
|
triCumulativeMagSf_(),
|
|
sumTriMagSf_(Pstream::nProcs() + 1, 0.0)
|
|
{
|
|
if (patchId_ < 0)
|
|
{
|
|
FatalErrorInFunction
|
|
<< "Requested patch " << patchName_ << " not found" << nl
|
|
<< "Available patches are: " << mesh.boundaryMesh().names() << nl
|
|
<< exit(FatalError);
|
|
}
|
|
|
|
updateMesh(mesh);
|
|
}
|
|
|
|
|
|
Foam::patchInjectionBase::patchInjectionBase(const patchInjectionBase& pib)
|
|
:
|
|
patchName_(pib.patchName_),
|
|
patchId_(pib.patchId_),
|
|
patchArea_(pib.patchArea_),
|
|
patchNormal_(pib.patchNormal_),
|
|
cellOwners_(pib.cellOwners_),
|
|
triFace_(pib.triFace_),
|
|
triToFace_(pib.triToFace_),
|
|
triCumulativeMagSf_(pib.triCumulativeMagSf_),
|
|
sumTriMagSf_(pib.sumTriMagSf_)
|
|
{}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
|
|
|
Foam::patchInjectionBase::~patchInjectionBase()
|
|
{}
|
|
|
|
|
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
|
|
void Foam::patchInjectionBase::updateMesh(const polyMesh& mesh)
|
|
{
|
|
// Set/cache the injector cells
|
|
const polyPatch& patch = mesh.boundaryMesh()[patchId_];
|
|
const pointField& points = patch.points();
|
|
|
|
cellOwners_ = patch.faceCells();
|
|
|
|
// Triangulate the patch faces and create addressing
|
|
DynamicList<label> triToFace(2*patch.size());
|
|
DynamicList<scalar> triMagSf(2*patch.size());
|
|
DynamicList<face> triFace(2*patch.size());
|
|
DynamicList<face> tris(5);
|
|
|
|
// Set zero value at the start of the tri area list
|
|
triMagSf.append(0.0);
|
|
|
|
forAll(patch, facei)
|
|
{
|
|
const face& f = patch[facei];
|
|
|
|
tris.clear();
|
|
f.triangles(points, tris);
|
|
|
|
forAll(tris, i)
|
|
{
|
|
triToFace.append(facei);
|
|
triFace.append(tris[i]);
|
|
triMagSf.append(tris[i].mag(points));
|
|
}
|
|
}
|
|
|
|
forAll(sumTriMagSf_, i)
|
|
{
|
|
sumTriMagSf_[i] = 0.0;
|
|
}
|
|
|
|
sumTriMagSf_[Pstream::myProcNo() + 1] = sum(triMagSf);
|
|
|
|
Pstream::listCombineGather(sumTriMagSf_, maxEqOp<scalar>());
|
|
Pstream::listCombineScatter(sumTriMagSf_);
|
|
|
|
for (label i = 1; i < triMagSf.size(); i++)
|
|
{
|
|
triMagSf[i] += triMagSf[i-1];
|
|
}
|
|
|
|
// Transfer to persistent storage
|
|
triFace_.transfer(triFace);
|
|
triToFace_.transfer(triToFace);
|
|
triCumulativeMagSf_.transfer(triMagSf);
|
|
|
|
// Convert sumTriMagSf_ into cumulative sum of areas per proc
|
|
for (label i = 1; i < sumTriMagSf_.size(); i++)
|
|
{
|
|
sumTriMagSf_[i] += sumTriMagSf_[i-1];
|
|
}
|
|
|
|
const scalarField magSf(mag(patch.faceAreas()));
|
|
patchArea_ = sum(magSf);
|
|
patchNormal_ = patch.faceAreas()/magSf;
|
|
reduce(patchArea_, sumOp<scalar>());
|
|
}
|
|
|
|
|
|
void Foam::patchInjectionBase::setPositionAndCell
|
|
(
|
|
const polyMesh& mesh,
|
|
cachedRandom& rnd,
|
|
vector& position,
|
|
label& cellOwner,
|
|
label& tetFacei,
|
|
label& tetPtI
|
|
)
|
|
{
|
|
scalar areaFraction = rnd.globalPosition(scalar(0), patchArea_);
|
|
|
|
if (cellOwners_.size() > 0)
|
|
{
|
|
// Determine which processor to inject from
|
|
label proci = 0;
|
|
forAllReverse(sumTriMagSf_, i)
|
|
{
|
|
if (areaFraction >= sumTriMagSf_[i])
|
|
{
|
|
proci = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Pstream::myProcNo() == proci)
|
|
{
|
|
// Find corresponding decomposed face triangle
|
|
label triI = 0;
|
|
scalar offset = sumTriMagSf_[proci];
|
|
forAllReverse(triCumulativeMagSf_, i)
|
|
{
|
|
if (areaFraction > triCumulativeMagSf_[i] + offset)
|
|
{
|
|
triI = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set cellOwner
|
|
label facei = triToFace_[triI];
|
|
cellOwner = cellOwners_[facei];
|
|
|
|
// Find random point in triangle
|
|
const polyPatch& patch = mesh.boundaryMesh()[patchId_];
|
|
const pointField& points = patch.points();
|
|
const face& tf = triFace_[triI];
|
|
const triPointRef tri(points[tf[0]], points[tf[1]], points[tf[2]]);
|
|
const point pf(tri.randomPoint(rnd));
|
|
|
|
// Position perturbed away from face (into domain)
|
|
const scalar a = rnd.position(scalar(0.1), scalar(0.5));
|
|
const vector& pc = mesh.cellCentres()[cellOwner];
|
|
const vector d = mag(pf - pc)*patchNormal_[facei];
|
|
|
|
position = pf - a*d;
|
|
|
|
// The position is between the face and cell centre, which could
|
|
// be in any tet of the decomposed cell, so arbitrarily choose the
|
|
// first face of the cell as the tetFace and the first point after
|
|
// the base point on the face as the tetPt. The tracking will pick
|
|
// the cell consistent with the motion in the first tracking step
|
|
tetFacei = mesh.cells()[cellOwner][0];
|
|
tetPtI = 1;
|
|
}
|
|
else
|
|
{
|
|
cellOwner = -1;
|
|
tetFacei = -1;
|
|
tetPtI = -1;
|
|
|
|
// Dummy position
|
|
position = pTraits<vector>::max;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cellOwner = -1;
|
|
tetFacei = -1;
|
|
tetPtI = -1;
|
|
|
|
// Dummy position
|
|
position = pTraits<vector>::max;
|
|
}
|
|
}
|
|
|
|
|
|
// ************************************************************************* //
|