/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd |
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2016-2017 Wikki 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 .
\*---------------------------------------------------------------------------*/
#include "faMesh.H"
#include "faMeshLduAddressing.H"
#include "areaFields.H"
#include "edgeFields.H"
#include "primitiveFacePatch.H"
#include "fac.H"
#include "processorFaPatch.H"
#include "wedgeFaPatch.H"
#include "PstreamCombineReduceOps.H"
#include "coordinateSystem.H"
#include "scalarMatrices.H"
#include "processorFaPatchFields.H"
#include "emptyFaPatchFields.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::faMesh::calcLduAddressing() const
{
DebugInFunction
<< "Calculating addressing" << endl;
if (lduPtr_)
{
FatalErrorInFunction
<< "lduPtr_ already allocated"
<< abort(FatalError);
}
lduPtr_ = new faMeshLduAddressing(*this);
}
void Foam::faMesh::calcPatchStarts() const
{
DebugInFunction
<< "Calculating patch starts" << endl;
if (patchStartsPtr_)
{
FatalErrorInFunction
<< "patchStartsPtr_ already allocated"
<< abort(FatalError);
}
patchStartsPtr_ = new labelList(boundary().size(), -1);
labelList& patchStarts = *patchStartsPtr_;
patchStarts[0] = nInternalEdges();
for (label i = 1; i < boundary().size(); ++i)
{
patchStarts[i] =
patchStarts[i - 1] + boundary()[i - 1].faPatch::size();
}
}
void Foam::faMesh::calcLe() const
{
DebugInFunction
<< "Calculating local edges" << endl;
if (LePtr_)
{
FatalErrorInFunction
<< "LePtr_ already allocated"
<< abort(FatalError);
}
LePtr_ =
new edgeVectorField
(
IOobject
(
"Le",
mesh().pointsInstance(),
meshSubDir,
mesh()
),
*this,
dimLength
);
edgeVectorField& Le = *LePtr_;
const pointField& pPoints = points();
const edgeList& pEdges = edges();
const edgeVectorField& eCentres = edgeCentres();
const areaVectorField& fCentres = areaCentres();
const edgeVectorField& edgeNormals = edgeAreaNormals();
vectorField& leInternal = Le.ref();
const vectorField& edgeNormalsInternal = edgeNormals.internalField();
const vectorField& fCentresInternal = fCentres.internalField();
const vectorField& eCentresInternal = eCentres.internalField();
const scalarField& magLeInternal = magLe().internalField();
forAll(leInternal, edgeI)
{
leInternal[edgeI] =
pEdges[edgeI].vec(pPoints) ^ edgeNormalsInternal[edgeI];
leInternal[edgeI] *=
- sign
(
leInternal[edgeI] &
(
fCentresInternal[owner()[edgeI]]
- eCentresInternal[edgeI]
)
);
leInternal[edgeI] *=
magLeInternal[edgeI]/mag(leInternal[edgeI]);
}
forAll(boundary(), patchI)
{
const labelUList& bndEdgeFaces = boundary()[patchI].edgeFaces();
const edgeList::subList bndEdges =
boundary()[patchI].patchSlice(pEdges);
const vectorField& bndEdgeNormals =
edgeNormals.boundaryField()[patchI];
vectorField& patchLe = Le.boundaryFieldRef()[patchI];
const vectorField& patchECentres = eCentres.boundaryField()[patchI];
forAll(patchLe, edgeI)
{
patchLe[edgeI] =
bndEdges[edgeI].vec(pPoints) ^ bndEdgeNormals[edgeI];
patchLe[edgeI] *=
- sign
(
patchLe[edgeI]&
(
fCentresInternal[bndEdgeFaces[edgeI]]
- patchECentres[edgeI]
)
);
patchLe[edgeI] *=
magLe().boundaryField()[patchI][edgeI]
/mag(patchLe[edgeI]);
}
}
}
void Foam::faMesh::calcMagLe() const
{
DebugInFunction
<< "Calculating local edge magnitudes" << endl;
if (magLePtr_)
{
FatalErrorInFunction
<< "magLePtr_ already allocated"
<< abort(FatalError);
}
magLePtr_ =
new edgeScalarField
(
IOobject
(
"magLe",
mesh().pointsInstance(),
meshSubDir,
mesh()
),
*this,
dimLength
);
edgeScalarField& magLe = *magLePtr_;
const pointField& localPoints = points();
const edgeList::subList internalEdges =
edgeList::subList(edges(), nInternalEdges());
forAll(internalEdges, edgeI)
{
magLe.ref()[edgeI] = internalEdges[edgeI].mag(localPoints);
}
forAll(boundary(), patchI)
{
const edgeList::subList patchEdges =
boundary()[patchI].patchSlice(edges());
forAll(patchEdges, edgeI)
{
magLe.boundaryFieldRef()[patchI][edgeI] =
patchEdges[edgeI].mag(localPoints);
}
}
}
void Foam::faMesh::calcAreaCentres() const
{
DebugInFunction
<< "Calculating face centres" << endl;
if (centresPtr_)
{
FatalErrorInFunction
<< "centresPtr_ already allocated"
<< abort(FatalError);
}
centresPtr_ =
new areaVectorField
(
IOobject
(
"centres",
mesh().pointsInstance(),
meshSubDir,
mesh()
),
*this,
dimLength
);
areaVectorField& centres = *centresPtr_;
const pointField& localPoints = points();
const faceList& localFaces = faces();
forAll(localFaces, faceI)
{
centres.ref()[faceI] = localFaces[faceI].centre(localPoints);
}
forAll(boundary(), patchI)
{
const edgeList::subList patchEdges =
boundary()[patchI].patchSlice(edges());
forAll(patchEdges, edgeI)
{
centres.boundaryFieldRef()[patchI][edgeI] =
patchEdges[edgeI].centre(localPoints);
}
}
forAll(centres.boundaryField(), patchI)
{
//HJ: this is wrong! 5/Aug/2011
if
(
isA
(
centres.boundaryField()[patchI]
)
)
{
centres.boundaryFieldRef()[patchI].initEvaluate();
centres.boundaryFieldRef()[patchI].evaluate();
}
}
}
void Foam::faMesh::calcEdgeCentres() const
{
DebugInFunction
<< "Calculating edge centres" << endl;
if (edgeCentresPtr_)
{
FatalErrorInFunction
<< "edgeCentresPtr_ already allocated"
<< abort(FatalError);
}
edgeCentresPtr_ =
new edgeVectorField
(
IOobject
(
"edgeCentres",
mesh().pointsInstance(),
meshSubDir,
mesh()
),
*this,
dimLength
);
edgeVectorField& edgeCentres = *edgeCentresPtr_;
const pointField& localPoints = points();
const edgeList::subList internalEdges =
edgeList::subList(edges(), nInternalEdges());
forAll(internalEdges, edgeI)
{
edgeCentres.ref()[edgeI] = internalEdges[edgeI].centre(localPoints);
}
forAll(boundary(), patchI)
{
const edgeList::subList patchEdges =
boundary()[patchI].patchSlice(edges());
forAll(patchEdges, edgeI)
{
edgeCentres.boundaryFieldRef()[patchI][edgeI] =
patchEdges[edgeI].centre(localPoints);
}
}
}
void Foam::faMesh::calcS() const
{
DebugInFunction
<< "Calculating areas" << endl;
if (SPtr_)
{
FatalErrorInFunction
<< "SPtr_ already allocated"
<< abort(FatalError);
}
SPtr_ = new DimensionedField
(
IOobject
(
"S",
time().timeName(),
mesh(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
*this,
dimArea
);
DimensionedField& S = *SPtr_;
const pointField& localPoints = points();
const faceList& localFaces = faces();
forAll(S, faceI)
{
S[faceI] = localFaces[faceI].mag(localPoints);
}
}
void Foam::faMesh::calcFaceAreaNormals() const
{
DebugInFunction
<< "Calculating face area normals" << endl;
if (faceAreaNormalsPtr_)
{
FatalErrorInFunction
<< "faceAreaNormalsPtr_ already allocated"
<< abort(FatalError);
}
faceAreaNormalsPtr_ =
new areaVectorField
(
IOobject
(
"faceAreaNormals",
mesh().pointsInstance(),
meshSubDir,
mesh()
),
*this,
dimless
);
areaVectorField& faceAreaNormals = *faceAreaNormalsPtr_;
const pointField& localPoints = points();
const faceList& localFaces = faces();
vectorField& nInternal = faceAreaNormals.ref();
forAll(localFaces, faceI)
{
nInternal[faceI] =
localFaces[faceI].normal(localPoints)/
localFaces[faceI].mag(localPoints);
}
forAll(boundary(), patchI)
{
faceAreaNormals.boundaryFieldRef()[patchI] =
edgeAreaNormals().boundaryField()[patchI];
}
forAll(faceAreaNormals.boundaryField(), patchI)
{
if
(
isA
(
faceAreaNormals.boundaryField()[patchI]
)
)
{
faceAreaNormals.boundaryFieldRef()[patchI].initEvaluate();
faceAreaNormals.boundaryFieldRef()[patchI].evaluate();
}
}
}
void Foam::faMesh::calcEdgeAreaNormals() const
{
DebugInFunction
<< "Calculating edge area normals" << endl;
if (edgeAreaNormalsPtr_)
{
FatalErrorInFunction
<< "edgeAreaNormalsPtr_ already allocated"
<< abort(FatalError);
}
edgeAreaNormalsPtr_ =
new edgeVectorField
(
IOobject
(
"edgeAreaNormals",
mesh().pointsInstance(),
meshSubDir,
mesh()
),
*this,
dimless
);
edgeVectorField& edgeAreaNormals = *edgeAreaNormalsPtr_;
// Point area normals
const vectorField& pointNormals = pointAreaNormals();
// // Primitive patch edge normals
// const labelListList& patchPointEdges = patch().pointEdges();
// vectorField patchEdgeNormals(nEdges(), vector::zero);
// forAll(pointNormals, pointI)
// {
// const labelList& curPointEdges = patchPointEdges[pointI];
// forAll(curPointEdges, edgeI)
// {
// label curEdge = curPointEdges[edgeI];
// patchEdgeNormals[curEdge] += 0.5*pointNormals[pointI];
// }
// }
// patchEdgeNormals /= mag(patchEdgeNormals);
// // Edge area normals
// label nIntEdges = patch().nInternalEdges();
// for (label edgeI = 0; edgeI < nIntEdges; ++edgeI)
// {
// edgeAreaNormals.ref()[edgeI] =
// patchEdgeNormals[edgeI];
// }
// forAll(boundary(), patchI)
// {
// const labelList& edgeLabels = boundary()[patchI];
// forAll(edgeAreaNormals.boundaryFieldRef()[patchI], edgeI)
// {
// edgeAreaNormals.boundaryFieldRef()[patchI][edgeI] =
// patchEdgeNormals[edgeLabels[edgeI]];
// }
// }
forAll(edgeAreaNormals.internalField(), edgeI)
{
vector e = edges()[edgeI].vec(points());
e /= mag(e);
// scalar wStart =
// 1.0 - sqr(mag(e^pointNormals[edges()[edgeI].end()]));
// scalar wEnd =
// 1.0 - sqr(mag(e^pointNormals[edges()[edgeI].start()]));
// wStart = 1.0;
// wEnd = 1.0;
// edgeAreaNormals.ref()[edgeI] =
// wStart*pointNormals[edges()[edgeI].start()]
// + wEnd*pointNormals[edges()[edgeI].end()];
// vector eC =
// 0.5
// *(
// points()[edges()[edgeI].start()]
// + points()[edges()[edgeI].end()]
// );
// vector eCp = 0.5*
// (
// points()[edges()[edgeI].start()]
// + pointNormals[edges()[edgeI].start()]
// points()[edges()[edgeI].end()] +
// );
edgeAreaNormals.ref()[edgeI] =
pointNormals[edges()[edgeI].start()]
+ pointNormals[edges()[edgeI].end()];
edgeAreaNormals.ref()[edgeI] -=
e*(e&edgeAreaNormals.internalField()[edgeI]);
}
edgeAreaNormals.ref() /= mag(edgeAreaNormals.internalField());
forAll(boundary(), patchI)
{
const edgeList::subList patchEdges =
boundary()[patchI].patchSlice(edges());
forAll(patchEdges, edgeI)
{
edgeAreaNormals.boundaryFieldRef()[patchI][edgeI] =
pointNormals[patchEdges[edgeI].start()]
+ pointNormals[patchEdges[edgeI].end()];
vector e = patchEdges[edgeI].vec(points());
e /= mag(e);
edgeAreaNormals.boundaryFieldRef()[patchI][edgeI] -=
e*(e&edgeAreaNormals.boundaryField()[patchI][edgeI]);
}
edgeAreaNormals.boundaryFieldRef()[patchI] /=
mag(edgeAreaNormals.boundaryField()[patchI]);
}
}
void Foam::faMesh::calcFaceCurvatures() const
{
DebugInFunction
<< "Calculating face curvatures" << endl;
if (faceCurvaturesPtr_)
{
FatalErrorInFunction
<< "faceCurvaturesPtr_ already allocated"
<< abort(FatalError);
}
faceCurvaturesPtr_ =
new areaScalarField
(
IOobject
(
"faceCurvatures",
mesh().pointsInstance(),
meshSubDir,
mesh()
),
*this,
dimless/dimLength
);
areaScalarField& faceCurvatures = *faceCurvaturesPtr_;
// faceCurvatures =
// fac::edgeIntegrate(Le()*edgeLengthCorrection())
// &faceAreaNormals();
areaVectorField kN(fac::edgeIntegrate(Le()*edgeLengthCorrection()));
faceCurvatures = sign(kN&faceAreaNormals())*mag(kN);
}
void Foam::faMesh::calcEdgeTransformTensors() const
{
DebugInFunction
<< "Calculating edge transformation tensors" << endl;
if (edgeTransformTensorsPtr_)
{
FatalErrorInFunction
<< "edgeTransformTensorsPtr_ already allocated"
<< abort(FatalError);
}
edgeTransformTensorsPtr_ = new FieldField(nEdges());
FieldField& edgeTransformTensors =
*edgeTransformTensorsPtr_;
const areaVectorField& Nf = faceAreaNormals();
const areaVectorField& Cf = areaCentres();
const edgeVectorField& Ne = edgeAreaNormals();
const edgeVectorField& Ce = edgeCentres();
// Internal edges transformation tensors
for (label edgeI=0; edgeI(3, I));
vector E = Ce.internalField()[edgeI];
if (skew())
{
E -= skewCorrectionVectors().internalField()[edgeI];
}
// Edge transformation tensor
vector il = E - Cf.internalField()[owner()[edgeI]];
il -= Ne.internalField()[edgeI]
*(Ne.internalField()[edgeI]&il);
il /= mag(il);
vector kl = Ne.internalField()[edgeI];
vector jl = kl^il;
edgeTransformTensors[edgeI][0] =
tensor
(
il.x(), il.y(), il.z(),
jl.x(), jl.y(), jl.z(),
kl.x(), kl.y(), kl.z()
);
// Owner transformation tensor
il = E - Cf.internalField()[owner()[edgeI]];
il -= Nf.internalField()[owner()[edgeI]]
*(Nf.internalField()[owner()[edgeI]]&il);
il /= mag(il);
kl = Nf.internalField()[owner()[edgeI]];
jl = kl^il;
edgeTransformTensors[edgeI][1] =
tensor
(
il.x(), il.y(), il.z(),
jl.x(), jl.y(), jl.z(),
kl.x(), kl.y(), kl.z()
);
// Neighbour transformation tensor
il = Cf.internalField()[neighbour()[edgeI]] - E;
il -= Nf.internalField()[neighbour()[edgeI]]
*(Nf.internalField()[neighbour()[edgeI]]&il);
il /= mag(il);
kl = Nf.internalField()[neighbour()[edgeI]];
jl = kl^il;
edgeTransformTensors[edgeI][2] =
tensor
(
il.x(), il.y(), il.z(),
jl.x(), jl.y(), jl.z(),
kl.x(), kl.y(), kl.z()
);
}
// Boundary edges transformation tensors
forAll(boundary(), patchI)
{
if (boundary()[patchI].coupled())
{
const labelUList& edgeFaces =
boundary()[patchI].edgeFaces();
vectorField ngbCf(Cf.boundaryField()[patchI].patchNeighbourField());
vectorField ngbNf(Nf.boundaryField()[patchI].patchNeighbourField());
forAll(edgeFaces, edgeI)
{
edgeTransformTensors.set
(
boundary()[patchI].start() + edgeI,
new Field(3, I)
);
vector E = Ce.boundaryField()[patchI][edgeI];
if (skew())
{
E -= skewCorrectionVectors()
.boundaryField()[patchI][edgeI];
}
// Edge transformation tensor
vector il = E - Cf.internalField()[edgeFaces[edgeI]];
il -= Ne.boundaryField()[patchI][edgeI]
*(Ne.boundaryField()[patchI][edgeI]&il);
il /= mag(il);
vector kl = Ne.boundaryField()[patchI][edgeI];
vector jl = kl^il;
edgeTransformTensors[boundary()[patchI].start() + edgeI][0] =
tensor(il, jl, kl);
// Owner transformation tensor
il = E - Cf.internalField()[edgeFaces[edgeI]];
il -= Nf.internalField()[edgeFaces[edgeI]]
*(Nf.internalField()[edgeFaces[edgeI]]&il);
il /= mag(il);
kl = Nf.internalField()[edgeFaces[edgeI]];
jl = kl^il;
edgeTransformTensors[boundary()[patchI].start() + edgeI][1] =
tensor(il, jl, kl);
// Neighbour transformation tensor
il = ngbCf[edgeI] - E;
il -= ngbNf[edgeI]*(ngbNf[edgeI]&il);
il /= mag(il);
kl = ngbNf[edgeI];
jl = kl^il;
edgeTransformTensors[boundary()[patchI].start() + edgeI][2] =
tensor(il, jl, kl);
}
}
else
{
const labelUList& edgeFaces = boundary()[patchI].edgeFaces();
forAll(edgeFaces, edgeI)
{
edgeTransformTensors.set
(
boundary()[patchI].start() + edgeI,
new Field(3, I)
);
vector E = Ce.boundaryField()[patchI][edgeI];
if (skew())
{
E -= skewCorrectionVectors()
.boundaryField()[patchI][edgeI];
}
// Edge transformation tensor
vector il = E - Cf.internalField()[edgeFaces[edgeI]];
il -= Ne.boundaryField()[patchI][edgeI]
*(Ne.boundaryField()[patchI][edgeI]&il);
il /= mag(il);
vector kl = Ne.boundaryField()[patchI][edgeI];
vector jl = kl^il;
edgeTransformTensors[boundary()[patchI].start() + edgeI][0] =
tensor(il, jl, kl);
// Owner transformation tensor
il = E - Cf.internalField()[edgeFaces[edgeI]];
il -= Nf.internalField()[edgeFaces[edgeI]]
*(Nf.internalField()[edgeFaces[edgeI]]&il);
il /= mag(il);
kl = Nf.internalField()[edgeFaces[edgeI]];
jl = kl^il;
edgeTransformTensors[boundary()[patchI].start() + edgeI][1] =
tensor(il, jl, kl);
}
}
}
}
Foam::labelList Foam::faMesh::internalPoints() const
{
DebugInFunction
<< "Calculating internal points" << endl;
const edgeList& edges = patch().edges();
label nIntEdges = patch().nInternalEdges();
List internal(nPoints(), true);
for (label curEdge = nIntEdges; curEdge < edges.size(); ++curEdge)
{
internal[edges[curEdge].start()] = false;
internal[edges[curEdge].end()] = false;
}
SLList