/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 .
Class
Foam::leastSquaresEdgeInterpolation
Description
Least-squares edge interpolation scheme class, from
face centers to points then from points to edges.
References:
\verbatim
Governing equations (tag:P):
Pesci, C. (2019).
Computational analysis of fluid interfaces
influenced by soluble surfactant.
Darmstadt, Technische Universität. PhD thesis.
URI:https://tuprints.ulb.tu-darmstadt.de/id/eprint/9303
\endverbatim
SourceFiles
leastSquaresEdgeInterpolationMake.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_leastSquaresEdgeInterpolation_H
#define Foam_leastSquaresEdgeInterpolation_H
#include "edgeInterpolationScheme.H"
#include "areaFields.H"
#include "edgeFields.H"
#include "leastSquaresFaGrad.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class leastSquaresEdgeInterpolation Declaration
\*---------------------------------------------------------------------------*/
template
class leastSquaresEdgeInterpolation
:
virtual public edgeInterpolationScheme
{
public:
//- Runtime type information
TypeName("leastSquares");
// Generated Methods
//- No copy construct
leastSquaresEdgeInterpolation(const leastSquaresEdgeInterpolation&)
= delete;
//- No copy assignment
void operator=(const leastSquaresEdgeInterpolation&) = delete;
// Constructors
//- Construct from mesh
leastSquaresEdgeInterpolation(const faMesh& mesh)
:
edgeInterpolationScheme(mesh)
{}
//- Construct from Istream
leastSquaresEdgeInterpolation(const faMesh& mesh, Istream&)
:
edgeInterpolationScheme(mesh)
{}
//- Construct from faceFlux and Istream
leastSquaresEdgeInterpolation
(
const faMesh& mesh,
const edgeScalarField&,
Istream&
)
:
edgeInterpolationScheme(mesh)
{}
// Member Functions
//- Return the edge-interpolate of the given face field
tmp>
interpolate
(
const GeometricField&
) const;
//- Return the interpolation weighting factors
tmp weights
(
const GeometricField&
) const
{
return this->mesh().edgeInterpolation::weights();
}
};
template
tmp>
leastSquaresEdgeInterpolation::interpolate
(
const GeometricField& af
) const
{
typedef typename outerProduct::type GradType;
typedef GeometricField GradFieldType;
typedef GeometricField EdgeFieldType;
typedef Field FieldType;
const faMesh& mesh = af.mesh();
const labelList& meshPts = mesh.patch().meshPoints();
const labelListList& pointFaceAddr = mesh.patch().pointFaces();
const areaVectorField& C = mesh.areaCentres();
tmp tgradAf= fa::leastSquaresFaGrad(mesh).grad(af);
const GradFieldType& gradAf = tgradAf.cref();
// Field at surface points, Pi (P:p. 29-30)
auto tPi = tmp::New(meshPts.size(), Zero);
FieldType& Pi = tPi.ref();
forAll(meshPts, i)
{
const label nFaces = pointFaceAddr[i].size();
FieldType Pij(nFaces);
vectorField dPC(nFaces);
for (label facei = 0; facei < nFaces; ++facei)
{
const label j = pointFaceAddr[i][facei];
// Euclidean distance between a point and face centres (P:Fig. 3.3)
dPC[facei] = mesh.points()[i] - C[j];
// (P:Eq. 3.14)
Pij[facei] = af[j] + (dPC[facei] & gradAf[j]);
}
const scalarField magdPC(max(mag(dPC), SMALL));
// (P:Eq. 3.15)
Pi[i] = sum(Pij/magdPC)/sum(scalar(1)/magdPC);
}
tgradAf.clear();
auto tinterp = tmp::New
(
IOobject
(
"interpolate(" + af.name() + ')',
af.instance(),
af.db()
),
af.mesh(),
af.dimensions()
);
EdgeFieldType& interp = tinterp.ref();
FieldType& interpEdges = interp.primitiveFieldRef();
const edgeList& faEdges = mesh.edges();
const label nInternalEdges = mesh.nInternalEdges();
// Internal field
for (label edgei = 0; edgei < nInternalEdges; ++edgei)
{
// (P:Eq. 3.16)
interpEdges[edgei] =
0.5*
(
Pi[faEdges[edgei].start()]
+ Pi[faEdges[edgei].end()]
);
}
// Boundary field from boundary condition [fixedValue]
// Coupled boundary fields are not handled
forAll(interp.boundaryField(), patchi)
{
interp.boundaryFieldRef()[patchi] = af.boundaryField()[patchi];
}
return tinterp;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //