37 namespace filmSeparationModels
45 FriedrichModel::separationType
47 FriedrichModel::separationTypeNames
49 { separationType::FULL,
"full" },
50 { separationType::PARTIAL ,
"partial" },
56 bitSet FriedrichModel::calcCornerEdges()
const 70 const label faceO = own[edgei];
71 const label faceN = nbr[edgei];
73 cornerEdges[edgei] = isCornerEdgeSharp
92 if (isA<processorFaPatch>(fap))
94 const label patchi = fap.index();
96 const label internalEdgei = fap.start();
98 const auto& faceCentresp = faceCentres.
boundaryField()[patchi];
99 const auto& faceNormalsp = faceNormals.
boundaryField()[patchi];
101 forAll(faceNormalsp, bndEdgei)
103 const label faceO = edgeFaces[bndEdgei];
104 const label meshEdgei = internalEdgei + bndEdgei;
106 cornerEdges[meshEdgei] = isCornerEdgeSharp
109 faceCentresp[bndEdgei],
111 faceNormalsp[bndEdgei]
121 bool FriedrichModel::isCornerEdgeSharp
123 const vector& faceCentreO,
124 const vector& faceCentreN,
125 const vector& faceNormalO,
130 const vector relativePosition(faceCentreN - faceCentreO);
133 const vector relativeNormal(faceNormalN - faceNormalO);
136 return ((relativeNormal & relativePosition) < -1
e-8);
140 scalarList FriedrichModel::calcCornerAngles()
const 152 if (!cornerEdges_[edgei])
continue;
154 const label faceO = own[edgei];
155 const label faceN = nbr[edgei];
157 cornerAngles[edgei] = calcCornerAngle
173 if (isA<processorFaPatch>(fap))
175 const label patchi = fap.index();
177 const label internalEdgei = fap.start();
179 const auto& faceNormalsp = faceNormals.
boundaryField()[patchi];
181 forAll(faceNormalsp, bndEdgei)
183 const label faceO = edgeFaces[bndEdgei];
184 const label meshEdgei = internalEdgei + bndEdgei;
186 if (!cornerEdges_[meshEdgei])
continue;
188 cornerAngles[meshEdgei] = calcCornerAngle
191 faceNormalsp[bndEdgei]
201 scalar FriedrichModel::calcCornerAngle
203 const vector& faceNormalO,
207 const scalar magFaceNormal =
mag(faceNormalO)*
mag(faceNormalN);
210 if (magFaceNormal < SMALL)
return 0;
212 scalar cosAngle = (faceNormalO & faceNormalN)/magFaceNormal;
213 cosAngle =
clamp(cosAngle, -1, 1);
219 bitSet FriedrichModel::calcSeparationFaces()
const 221 bitSet separationFaces(
mesh().faces().size(),
false);
231 if (!cornerEdges_[edgei])
continue;
233 const label faceO = own[edgei];
234 const label faceN = nbr[edgei];
254 if (isA<processorFaPatch>(fap))
256 const label patchi = fap.index();
258 const label internalEdgei = fap.start();
264 const label faceO = edgeFaces[bndEdgei];
265 const label meshEdgei(internalEdgei + bndEdgei);
267 if (!cornerEdges_[meshEdgei])
continue;
279 return separationFaces;
283 void FriedrichModel::isSeparationFace
286 const scalar phiEdge,
291 const scalar tol = 1
e-8;
296 separationFaces[faceO] =
true;
298 else if ((phiEdge < -tol) && (faceN != -1))
300 separationFaces[faceN] =
true;
305 scalarList FriedrichModel::calcSeparationAngles
307 const bitSet& separationFaces
318 if (!cornerEdges_[edgei])
continue;
320 const label faceO = own[edgei];
321 const label faceN = nbr[edgei];
323 if (separationFaces[faceO])
325 separationAngles[faceO] = cornerAngles_[edgei];
328 if (separationFaces[faceN])
330 separationAngles[faceN] = cornerAngles_[edgei];
344 if (isA<processorFaPatch>(fap))
346 const label patchi = fap.index();
348 const label internalEdgei = fap.start();
354 const label faceO = edgeFaces[bndEdgei];
355 const label meshEdgei(internalEdgei + bndEdgei);
357 if (!cornerEdges_[meshEdgei])
continue;
359 if (separationFaces[faceO])
361 separationAngles[faceO] = cornerAngles_[meshEdgei];
367 return separationAngles;
381 const bitSet separationFaces(calcSeparationFaces());
384 const scalarList separationAngles(calcSeparationAngles(separationFaces));
388 auto& Fratio = tFratio.ref();
391 forAll(separationFaces, i)
394 if (!separationFaces[i])
continue;
397 const scalar sinAngle =
std::sin(separationAngles[i]);
398 const scalar cosAngle =
std::cos(separationAngles[i]);
413 sigma[i]*(sinAngle + 1.0) +
rho[i]*magG_*
h[i]*Lb*cosAngle;
431 if (isA<processorFaPatch>(fap))
433 const label patchi = fap.index();
434 const label internalEdgei = fap.
start();
436 const auto& hp =
h.boundaryField()[patchi];
437 const auto& Ufp =
Uf.boundaryField()[patchi];
438 const auto& Upp = Up.boundaryField()[patchi];
439 const auto& rhop =
rho.boundaryField()[patchi];
440 const auto& sigmap =
sigma.boundaryField()[patchi];
441 const auto& mup =
mu.boundaryField()[patchi];
446 if (!separationFaces[i])
continue;
448 const label meshEdgei = internalEdgei + i;
451 const scalar sinAngle =
std::sin(cornerAngles_[meshEdgei]);
452 const scalar cosAngle =
std::cos(cornerAngles_[meshEdgei]);
455 const scalar
Re = hp[i]*
mag(Ufp[i])*rhop[i]/mup[i];
458 const vector Urelp(Upp[i] - Ufp[i]);
459 const scalar We = hp[i]*rhop_*
sqr(
mag(Urelp))/(2.0*sigmap[i]);
468 sigmap[i]*(sinAngle + 1.0)
469 + rhop[i]*magG_*hp[i]*Lb*cosAngle;
474 Fratio[i] = rhop[i]*
sqr(
mag(Ufp[i]))*hp[i]*sinAngle/den;
495 separationTypeNames.getOrDefault
502 rhop_(
dict.getScalar(
"rhop")),
503 magG_(
mag(film.
g().value())),
504 C0_(
dict.getOrDefault<scalar>(
"C0", 0.882)),
505 C1_(
dict.getOrDefault<scalar>(
"C1", -1.908)),
506 C2_(
dict.getOrDefault<scalar>(
"C2", 1.264)),
507 cornerEdges_(calcCornerEdges()),
508 cornerAngles_(calcCornerAngles())
513 <<
"Primary-phase density, rhop: " << rhop_ <<
" must be non-zero." 517 if (
mag(C2_) < VSMALL)
520 <<
"Empirical constant, C2 = " << C2_ <<
"cannot be zero." 531 const auto& Fratio = tFratio.
cref();
535 auto& separated = tseparated.ref();
540 case separationType::FULL:
551 case separationType::PARTIAL:
558 separated[i] = C0_ + C1_*
Foam::exp(-Fratio[i]/C2_);
572 mesh().newIOobject(
"Fratio"),
576 areaFratio.primitiveFieldRef() = Fratio;
dimensionedScalar acos(const dimensionedScalar &ds)
addToRunTimeSelectionTable(filmSeparationModel, FriedrichModel, dictionary)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
A list of keyword definitions, which are a keyword followed by a number of values (eg...
virtual const areaScalarField & sigma() const =0
Access const reference sigma.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Unit conversion functions.
UPtrList< const labelUList > edgeFaces() const
Return a list of edgeFaces for each patch.
dimensionedScalar sqrt(const dimensionedScalar &ds)
const T & cref() const
Return const reference to the object or to the contents of a (non-null) managed pointer.
static bool & parRun() noexcept
Test if this a parallel run.
const edgeScalarField & phi2s() const noexcept
Access continuity flux.
const areaVectorField & areaCentres() const
Return face centres as areaVectorField.
dimensionedScalar sigma("sigma", dimMass/sqr(dimTime), transportProperties)
Macros for easy insertion into run-time selection tables.
#define forAll(list, i)
Loop across all elements in list.
const dimensionedScalar e
Elementary charge.
dimensionedScalar cos(const dimensionedScalar &ds)
dimensionedScalar exp(const dimensionedScalar &ds)
const faMesh & mesh() const noexcept
Return const access to the finite-area mesh.
const areaScalarField & h() const noexcept
Access const reference h.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
autoPtr< surfaceVectorField > Uf
errorManip< error > abort(error &err)
edgeScalarField phis(IOobject("phis", runTime.timeName(), aMesh.thisDb(), IOobject::NO_READ, IOobject::NO_WRITE), linearEdgeInterpolate(Us) &aMesh.Le())
const uniformDimensionedVectorField & g
dimensionedScalar sin(const dimensionedScalar &ds)
virtual tmp< scalarField > separatedMassRatio() const
Calculate the mass ratio of film separation.
const dimensionSet dimForce
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
int debug
Static debugging option.
Finite area patch class. Used for 2-D non-Euclidian finite area method.
const faBoundaryMesh & boundary() const noexcept
Return constant reference to boundary mesh.
label start() const
The start label of the edges in the faMesh edges list.
const dimensionedScalar h
Planck constant.
A base class for filmSeparation models.
const dimensionedScalar mu
Atomic mass unit.
scalarField Re(const UList< complex > &cmplx)
Extract real component.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
virtual const areaScalarField & rho() const =0
Access const reference rho.
const polyBoundaryMesh & patches
defineTypeNameAndDebug(FriedrichModel, 0)
const labelList & edgeNeighbour() const noexcept
Edge neighbour addressing.
Finite area boundary mesh, which is a faPatch list with registered IO, a reference to the associated ...
const areaVectorField & Uf() const noexcept
Access const reference Uf.
const regionModels::areaSurfaceFilmModels::liquidFilmBase & film() const
Return const access to the film properties.
virtual const areaScalarField & mu() const =0
Access const reference mu.
A class for managing temporary objects.
FriedrichModel(const regionModels::areaSurfaceFilmModels::liquidFilmBase &film, const dictionary &dict)
Construct from the base film model and dictionary.
const areaVectorField & faceAreaNormals() const
Return face area normals.
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
const labelList & edgeOwner() const noexcept
Edge owner addressing.
dimensionSet clamp(const dimensionSet &a, const dimensionSet &range)
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
static constexpr const zero Zero
Global zero (0)