Newer
Older
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 "MRFZone.H"
#include "fvMesh.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "fvMatrices.H"
#include "syncTools.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
Henry
committed
defineTypeNameAndDebug(MRFZone, 0);
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::MRFZone::setMRFFaces()
// Type per face:
// 0:not in zone
// 1:moving with frame
// 2:other
labelList faceType(mesh_.nFaces(), Zero);
// Determine faces in cell zone
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// (without constructing cells)
const labelList& own = mesh_.faceOwner();
const labelList& nei = mesh_.faceNeighbour();
// Cells in zone
boolList zoneCell(mesh_.nCells(), false);
if (cellZoneID_ != -1)
const labelList& cellLabels = mesh_.cellZones()[cellZoneID_];
forAll(cellLabels, i)
zoneCell[cellLabels[i]] = true;
}
}
for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
if (zoneCell[own[facei]] || zoneCell[nei[facei]])
labelHashSet excludedPatches(excludedPatchLabels_);
forAll(patches, patchi)
const polyPatch& pp = patches[patchi];
if (pp.coupled() || excludedPatches.found(patchi))
label facei = pp.start()+i;
if (zoneCell[own[facei]])
nZoneFaces++;
}
}
}
else if (!isA<emptyPolyPatch>(pp))
{
forAll(pp, i)
label facei = pp.start()+i;
if (zoneCell[own[facei]])
// Synchronize the faceType across processor patches
syncTools::syncFaceList(mesh_, faceType, maxEqOp<label>());
// Now we have for faceType:
// 0 : face not in cellZone
// 1 : internal face or normal patch face
// 2 : coupled patch face or excluded patch face
// Sort into lists per patch.
internalFaces_.setSize(mesh_.nFaces());
label nInternal = 0;
for (label facei = 0; facei < mesh_.nInternalFaces(); facei++)
if (faceType[facei] == 1)
internalFaces_[nInternal++] = facei;
labelList nIncludedFaces(patches.size(), Zero);
labelList nExcludedFaces(patches.size(), Zero);
forAll(patches, patchi)
{
const polyPatch& pp = patches[patchi];
forAll(pp, patchFacei)
{
label facei = pp.start() + patchFacei;
if (faceType[facei] == 1)
else if (faceType[facei] == 2)
{
nExcludedFaces[patchi]++;
}
}
}
includedFaces_.setSize(patches.size());
excludedFaces_.setSize(patches.size());
forAll(nIncludedFaces, patchi)
{
includedFaces_[patchi].setSize(nIncludedFaces[patchi]);
excludedFaces_[patchi].setSize(nExcludedFaces[patchi]);
}
nIncludedFaces = 0;
nExcludedFaces = 0;
forAll(patches, patchi)
{
const polyPatch& pp = patches[patchi];
forAll(pp, patchFacei)
{
label facei = pp.start() + patchFacei;
if (faceType[facei] == 1)
{
includedFaces_[patchi][nIncludedFaces[patchi]++] = patchFacei;
}
else if (faceType[facei] == 2)
{
excludedFaces_[patchi][nExcludedFaces[patchi]++] = patchFacei;
}
}
}
faceSet internalFaces(mesh_, "internalFaces", internalFaces_);
Pout<< "Writing " << internalFaces.size()
<< " internal faces in MRF zone to faceSet "
<< internalFaces.name() << endl;
internalFaces.write();
faceSet MRFFaces(mesh_, "includedFaces", 100);
forAll(includedFaces_, patchi)
forAll(includedFaces_[patchi], i)
label patchFacei = includedFaces_[patchi][i];
MRFFaces.insert(patches[patchi].start()+patchFacei);
Pout<< "Writing " << MRFFaces.size()
<< " patch faces in MRF zone to faceSet "
<< MRFFaces.name() << endl;
MRFFaces.write();
faceSet excludedFaces(mesh_, "excludedFaces", 100);
forAll(excludedFaces_, patchi)
forAll(excludedFaces_[patchi], i)
label patchFacei = excludedFaces_[patchi][i];
excludedFaces.insert(patches[patchi].start()+patchFacei);
Pout<< "Writing " << excludedFaces.size()
<< " faces in MRF zone with special handling to faceSet "
<< excludedFaces.name() << endl;
excludedFaces.write();
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::MRFZone::MRFZone
(
const word& name,
const fvMesh& mesh,
const dictionary& dict,
const word& cellZoneName
cellZoneID_(-1),
excludedPatchNames_(wordRes()),
origin_(Zero),
axis_(Zero),
omega_(nullptr)
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::vector Foam::MRFZone::Omega() const
{
return omega_->value(mesh_.time().timeOutputValue())*axis_;
}
void Foam::MRFZone::addCoriolis
(
const volVectorField& U,
volVectorField& ddtU
) const
{
if (cellZoneID_ == -1)
{
return;
}
const labelList& cells = mesh_.cellZones()[cellZoneID_];
vectorField& ddtUc = ddtU.primitiveFieldRef();
const vectorField& Uc = U;
const vector Omega = this->Omega();
forAll(cells, i)
{
label celli = cells[i];
ddtUc[celli] += (Omega ^ Uc[celli]);
}
}
void Foam::MRFZone::addCoriolis(fvVectorMatrix& UEqn, const bool rhs) const
{
if (cellZoneID_ == -1)
{
return;
}
const labelList& cells = mesh_.cellZones()[cellZoneID_];
const scalarField& V = mesh_.V();
vectorField& Usource = UEqn.source();
const vectorField& U = UEqn.psi();
const vector Omega = this->Omega();
forAll(cells, i)
{
label celli = cells[i];
Usource[celli] += V[celli]*(Omega ^ U[celli]);
}
}
else
{
forAll(cells, i)
{
label celli = cells[i];
Usource[celli] -= V[celli]*(Omega ^ U[celli]);
}
void Foam::MRFZone::addCoriolis
(
const volScalarField& rho,
) const
{
if (cellZoneID_ == -1)
{
return;
}
const labelList& cells = mesh_.cellZones()[cellZoneID_];
const scalarField& V = mesh_.V();
vectorField& Usource = UEqn.source();
const vectorField& U = UEqn.psi();
const vector Omega = this->Omega();
forAll(cells, i)
{
label celli = cells[i];
Usource[celli] += V[celli]*rho[celli]*(Omega ^ U[celli]);
}
}
else
{
forAll(cells, i)
{
label celli = cells[i];
Usource[celli] -= V[celli]*rho[celli]*(Omega ^ U[celli]);
}
}
}
Henry
committed
void Foam::MRFZone::makeRelative(volVectorField& U) const
if (cellZoneID_ == -1)
{
return;
}
const volVectorField& C = mesh_.C();
const vector Omega = this->Omega();
const labelList& cells = mesh_.cellZones()[cellZoneID_];
forAll(cells, i)
{
label celli = cells[i];
}
// Included patches
volVectorField::Boundary& Ubf = U.boundaryFieldRef();
forAll(includedFaces_, patchi)
{
forAll(includedFaces_[patchi], i)
{
label patchFacei = includedFaces_[patchi][i];
Ubf[patchi][patchFacei] = Zero;
}
}
// Excluded patches
forAll(excludedFaces_, patchi)
{
forAll(excludedFaces_[patchi], i)
{
label patchFacei = excludedFaces_[patchi][i];
Ubf[patchi][patchFacei] -=
^ (C.boundaryField()[patchi][patchFacei] - origin_));
void Foam::MRFZone::makeRelative(surfaceScalarField& phi) const
{
makeRelativeRhoFlux(geometricOneField(), phi);
}
void Foam::MRFZone::makeRelative(FieldField<fvsPatchField, scalar>& phi) const
{
makeRelativeRhoFlux(oneFieldField(), phi);
}
void Foam::MRFZone::makeRelative(Field<scalar>& phi, const label patchi) const
{
makeRelativeRhoFlux(oneField(), phi, patchi);
}
void Foam::MRFZone::makeRelative
(
const surfaceScalarField& rho,
surfaceScalarField& phi
) const
{
makeRelativeRhoFlux(rho, phi);
}
Henry
committed
void Foam::MRFZone::makeAbsolute(volVectorField& U) const
if (cellZoneID_ == -1)
{
return;
}
const volVectorField& C = mesh_.C();
const vector Omega = this->Omega();
const labelList& cells = mesh_.cellZones()[cellZoneID_];
forAll(cells, i)
{
label celli = cells[i];
}
// Included patches
volVectorField::Boundary& Ubf = U.boundaryFieldRef();
forAll(includedFaces_, patchi)
{
forAll(includedFaces_[patchi], i)
{
label patchFacei = includedFaces_[patchi][i];
Ubf[patchi][patchFacei] =
(Omega ^ (C.boundaryField()[patchi][patchFacei] - origin_));
}
}
// Excluded patches
forAll(excludedFaces_, patchi)
{
forAll(excludedFaces_[patchi], i)
{
label patchFacei = excludedFaces_[patchi][i];
Ubf[patchi][patchFacei] +=
(Omega ^ (C.boundaryField()[patchi][patchFacei] - origin_));
}
}
}
void Foam::MRFZone::makeAbsolute(surfaceScalarField& phi) const
Henry
committed
makeAbsoluteRhoFlux(geometricOneField(), phi);
void Foam::MRFZone::makeAbsolute
(
const surfaceScalarField& rho,
surfaceScalarField& phi
) const
{
Henry
committed
makeAbsoluteRhoFlux(rho, phi);
void Foam::MRFZone::correctBoundaryVelocity(volVectorField& U) const
{
if (!active_)
{
return;
}
const vector Omega = this->Omega();
volVectorField::Boundary& Ubf = U.boundaryFieldRef();
const vectorField& patchC = mesh_.Cf().boundaryField()[patchi];
vectorField pfld(Ubf[patchi]);
forAll(includedFaces_[patchi], i)
{
label patchFacei = includedFaces_[patchi][i];
pfld[patchFacei] = (Omega ^ (patchC[patchFacei] - origin_));
Ubf[patchi] == pfld;
os.beginBlock(name_);
os.writeEntry("active", active_);
os.writeEntry("cellZone", cellZoneName_);
os.writeEntry("origin", origin_);
os.writeEntry("axis", axis_);
os.writeEntry("nonRotatingPatches", excludedPatchNames_);
os.endBlock();
bool Foam::MRFZone::read(const dictionary& dict)
{
coeffs_ = dict;
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
coeffs_.readIfPresent("active", active_);
if (!active_)
{
cellZoneID_ = -1;
return true;
}
coeffs_.readIfPresent("nonRotatingPatches", excludedPatchNames_);
origin_ = coeffs_.get<vector>("origin");
axis_ = coeffs_.get<vector>("axis").normalise();
omega_.reset(Function1<scalar>::New("omega", coeffs_, &mesh_));
const word oldCellZoneName = cellZoneName_;
if (cellZoneName_ == word::null)
{
coeffs_.readEntry("cellZone", cellZoneName_);
}
else
{
coeffs_.readIfPresent("cellZone", cellZoneName_);
}
if (cellZoneID_ == -1 || oldCellZoneName != cellZoneName_)
{
cellZoneID_ = mesh_.cellZones().findZoneID(cellZoneName_);
const labelHashSet excludedPatchSet
(
mesh_.boundaryMesh().patchSet(excludedPatchNames_)
);
excludedPatchLabels_.setSize(excludedPatchSet.size());
label i = 0;
for (const label patchi : excludedPatchSet)
{
excludedPatchLabels_[i++] = patchi;
}
bool cellZoneFound = (cellZoneID_ != -1);
reduce(cellZoneFound, orOp<bool>());
if (!cellZoneFound)
{
FatalErrorInFunction
<< "cannot find MRF cellZone " << cellZoneName_
<< exit(FatalError);
}
setMRFFaces();
}
Henry Weller
committed
void Foam::MRFZone::update()
{
if (mesh_.topoChanging())
{
setMRFFaces();
}
}
// ************************************************************************* //