curvatureSeparation.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2020-2024 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "curvatureSeparation.H"
31 
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36 namespace regionModels
37 {
38 namespace areaSurfaceFilmModels
39 {
40 
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 
43 defineTypeNameAndDebug(curvatureSeparation, 0);
45 (
46  injectionModel,
49 );
50 
51 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
52 
54 (
55  const areaVectorField& U,
56  const scalarField& calcCosAngle
57 ) const
58 {
59  const dimensionedScalar smallU(dimVelocity, ROOTVSMALL);
60  const areaVectorField UHat(U/(mag(U) + smallU));
61  auto tinvR1 = areaScalarField::New
62  (
63  "invR1",
65  (UHat & (UHat & -gradNHat_))
66  );
67 
68  scalarField& invR1 = tinvR1.ref().primitiveFieldRef();
69 
70  // apply defined patch radii
71  const scalar rMin = 1e-6;
72  const scalar definedInvR1 = 1.0/max(rMin, definedPatchRadii_);
73 
74  if (definedPatchRadii_ > 0)
75  {
76  invR1 = definedInvR1;
77  }
78 
79  // filter out large radii
80  const scalar rMax = 1e6;
81  forAll(invR1, i)
82  {
83  if ((mag(invR1[i]) < 1/rMax))
84  {
85  invR1[i] = -1.0;
86  }
87  }
88 
89  return tinvR1;
90 }
91 
92 
94 (
95  const edgeScalarField& phi
96 ) const
97 {
98  const areaVectorField& U = film().Uf();
99  const dimensionedScalar smallU(dimVelocity, ROOTVSMALL);
100  const areaVectorField UHat(U/(mag(U) + smallU));
101 
102  const faMesh& mesh = film().regionMesh();
103  const labelUList& own = mesh.edgeOwner();
104  const labelUList& nbr = mesh.edgeNeighbour();
105 
106  scalarField phiMax(mesh.nFaces(), -GREAT);
107  scalarField cosAngle(UHat.size(), Zero);
108 
109  const scalarField invR1(calcInvR1(U, cosAngle));
110 
111  forAll(nbr, edgei)
112  {
113  const label cellO = own[edgei];
114  const label cellN = nbr[edgei];
115 
116  if (phi[edgei] > phiMax[cellO])
117  {
118  phiMax[cellO] = phi[edgei];
119  cosAngle[cellO] = -gHat_ & UHat[cellN];
120  }
121  if (-phi[edgei] > phiMax[cellN])
122  {
123  phiMax[cellN] = -phi[edgei];
124  cosAngle[cellN] = -gHat_ & UHat[cellO];
125  }
126  }
127 
128  cosAngle *= pos(invR1);
129 
130  // checks
131  if (debug && mesh.time().writeTime())
132  {
133  {
134  areaScalarField volCosAngle
135  (
136  mesh.newIOobject("cosAngle"),
137  mesh,
139  );
140  volCosAngle.primitiveFieldRef() = cosAngle;
141  volCosAngle.correctBoundaryConditions();
142  volCosAngle.write();
143  }
144  }
145 
146  return clamp(cosAngle, scalarMinMax(-1, 1));
147 }
148 
149 
150 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
151 
152 curvatureSeparation::curvatureSeparation
153 (
154  liquidFilmBase& film,
155  const dictionary& dict
156 )
157 :
158  injectionModel(type(), film, dict),
159  gradNHat_(fac::grad(film.regionMesh().faceAreaNormals())),
160  deltaByR1Min_(coeffDict_.getOrDefault<scalar>("deltaByR1Min", 0)),
161  definedPatchRadii_
162  (
163  coeffDict_.getOrDefault<scalar>("definedPatchRadii", 0)
164  ),
165  magG_(mag(film.g().value())),
166  gHat_(Zero),
167  fThreshold_
168  (
169  coeffDict_.getOrDefault<scalar>("fThreshold", 1e-8)
170  ),
171  minInvR1_
172  (
173  coeffDict_.getOrDefault<scalar>("minInvR1", 5)
174  )
175 {
176  if (magG_ < ROOTVSMALL)
177  {
179  << "Acceleration due to gravity must be non-zero"
180  << exit(FatalError);
181  }
182 
184 }
185 
186 
187 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
188 
190 (
191  scalarField& availableMass,
192  scalarField& massToInject,
193  scalarField& diameterToInject
194 )
195 {
196  const faMesh& mesh = film().regionMesh();
197 
198  const areaScalarField& delta = film().h();
199  const areaVectorField& U = film().Uf();
200  const edgeScalarField& phi = film().phi2s();
201  const areaScalarField& rho = film().rho();
202  const scalarField magSqrU(magSqr(film().Uf()));
203  const areaScalarField& sigma = film().sigma();
204 
205  const scalarField cosAngle(calcCosAngle(phi));
206  const scalarField invR1(calcInvR1(U, cosAngle));
207 
208 
209  // calculate force balance
210  scalarField Fnet(mesh.nFaces(), Zero);
211  scalarField separated(mesh.nFaces(), Zero);
212 
213  forAll(invR1, i)
214  {
215  if ((invR1[i] > minInvR1_) && (delta[i]*invR1[i] > deltaByR1Min_))
216  {
217  const scalar R1 = 1.0/(invR1[i] + ROOTVSMALL);
218  const scalar R2 = R1 + delta[i];
219 
220  // inertial force
221  const scalar Fi = -delta[i]*rho[i]*magSqrU[i]*72.0/60.0*invR1[i];
222 
223  // body force
224  const scalar Fb =
225  - 0.5*rho[i]*magG_*invR1[i]*(sqr(R1) - sqr(R2))*cosAngle[i];
226 
227  // surface force
228  const scalar Fs = sigma[i]/R2;
229 
230  Fnet[i] = Fi + Fb + Fs;
231 
232  if (Fnet[i] + fThreshold_ < 0)
233  {
234  separated[i] = 1.0;
235  }
236  }
237  }
238 
239  // inject all available mass
240  massToInject = separated*availableMass;
241  diameterToInject = separated*delta;
242  availableMass -= separated*availableMass;
243 
244  addToInjectedMass(sum(massToInject));
245 
246  if (debug && mesh.time().writeTime())
247  {
248  {
249  areaScalarField volFnet
250  (
251  mesh.newIOobject("Fnet"),
252  mesh,
254  );
255  volFnet.primitiveFieldRef() = Fnet;
256  volFnet.write();
257  }
258 
259  {
260  areaScalarField areaSeparated
261  (
262  mesh.newIOobject("separated"),
263  mesh,
265  );
266  areaSeparated.primitiveFieldRef() = separated;
267  areaSeparated.write();
268  }
269 
270  {
271  areaScalarField areaMassToInject
272  (
273  mesh.newIOobject("massToInject"),
274  mesh,
276  );
277  areaMassToInject.primitiveFieldRef() = massToInject;
278  areaMassToInject.write();
279  }
280 
281  {
282  areaScalarField areaInvR1
283  (
284  mesh.newIOobject("InvR1"),
285  mesh,
287  );
288  areaInvR1.primitiveFieldRef() = invR1;
289  areaInvR1.write();
290  }
291  }
292 
294 }
295 
296 
297 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
298 
299 } // End namespace areaSurfaceFilmModels
300 } // End namespace regionModels
301 } // End namespace Foam
302 
303 // ************************************************************************* //
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition: faMesh.H:133
scalar delta
const Type & value() const noexcept
Return const reference to value.
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
void addToInjectedMass(const scalar dMass)
Add to injected mass.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &f1)
Calculate the second temporal derivative.
MinMax< scalar > scalarMinMax
A scalar min/max range.
Definition: MinMax.H:97
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
virtual const areaScalarField & sigma() const =0
Access const reference sigma.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
dimensionedSphericalTensor inv(const dimensionedSphericalTensor &dt)
scalar deltaByR1Min_
Minimum gravity driven film thickness (non-dimensionalised delta/R1)
const edgeScalarField & phi2s() const noexcept
Access continuity flux.
const dimensionSet dimless
Dimensionless.
defineTypeNameAndDebug(kinematicThinFilm, 0)
dimensionedScalar sigma("sigma", dimMass/sqr(dimTime), transportProperties)
Base class for film injection models, handling mass transfer from the film.
areaTensorField gradNHat_
Gradient of surface normals.
Macros for easy insertion into run-time selection tables.
tmp< scalarField > calcCosAngle(const edgeScalarField &phi) const
Calculate the cosine of the angle between gravity vector and cell out flow direction.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
tmp< areaScalarField > calcInvR1(const areaVectorField &U, const scalarField &calcCosAngle) const
Calculate local (inverse) radius of curvature.
dimensionedScalar pos(const dimensionedScalar &ds)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
addToRunTimeSelectionTable(liquidFilmBase, kinematicThinFilm, dictionary)
const uniformDimensionedVectorField & g() const noexcept
Gravity.
const areaScalarField & h() const noexcept
Access const reference h.
const faMesh & regionMesh() const
Return the region mesh database.
autoPtr< surfaceVectorField > Uf
static tmp< GeometricField< scalar, faPatchField, areaMesh > > New(const word &name, IOobjectOption::registerOption regOpt, const Mesh &mesh, const dimensionSet &dims, const word &patchFieldType=faPatchField< scalar >::calculatedType())
Return tmp field (NO_READ, NO_WRITE) from name, mesh, dimensions and patch type. [Takes current timeN...
const uniformDimensionedVectorField & g
const dimensionSet dimForce
int debug
Static debugging option.
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field values.
U
Definition: pEqn.H:72
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
virtual const areaScalarField & rho() const =0
Access const reference rho.
const areaVectorField & Uf() const noexcept
Access const reference Uf.
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:49
A class for managing temporary objects.
Definition: HashPtrTable.H:50
An indexed form of CGAL::Triangulation_face_base_2<K> used to keep track of the vertices in the trian...
Definition: indexedFace.H:43
Do not request registration (bool: false)
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Namespace for OpenFOAM.
tmp< GeometricField< typename outerProduct< vector, Type >::type, faPatchField, areaMesh >> grad(const GeometricField< Type, faePatchField, edgeMesh > &ssf)
Definition: facGrad.C:51
dimensionSet clamp(const dimensionSet &a, const dimensionSet &range)
Definition: dimensionSet.C:271
GeometricField< scalar, faPatchField, areaMesh > areaScalarField
Definition: areaFieldsFwd.H:72
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127
const dimensionSet dimVelocity
const liquidFilmBase & film() const
Return const access to the film surface film model.