isothermalFilm.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2023-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "isothermalFilm.H"
27 #include "filmWallPolyPatch.H"
28 #include "filmSurfacePolyPatch.H"
29 #include "mappedFvPatchBaseBase.H"
32 #include "constantSurfaceTension.H"
33 #include "fvcVolumeIntegrate.H"
34 #include "fvcDdt.H"
35 #include "fvcDiv.H"
36 #include "fvcFlux.H"
37 #include "fvcSurfaceIntegrate.H"
39 
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44 namespace solvers
45 {
48 }
49 }
50 
51 
52 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
53 
54 bool Foam::solvers::isothermalFilm::initFilmMesh()
55 {
56  // Search for film wall patches
57 
58  label nWallFaces = 0;
59  DynamicList<label> wallPatchIndices_;
60 
61  const polyBoundaryMesh& bm = mesh.poly().boundary();
62 
63  forAll(bm, patchi)
64  {
65  const polyPatch& p = bm[patchi];
66 
67  if (isA<filmWallPolyPatch>(p))
68  {
69  wallPatchIndices_.append(patchi);
70  nWallFaces += p.faceCells().size();
71  }
72  }
73 
74  if (nWallFaces != mesh.nCells())
75  {
77  << "The number of film wall faces in the mesh "
78  << nWallFaces
79  << " is not equal to the number of cells "
80  << mesh.nCells()
81  << exit(FatalError);
82  }
83 
84  if (returnReduce(nWallFaces, sumOp<label>()) == 0)
85  {
87  << "There are no filmWall faces in the mesh"
88  << exit(FatalError);
89  }
90 
91  wallPatchIDs.transfer(wallPatchIndices_);
92 
93 
94  // Search for film surface patch
95  surfacePatchID = -1;
96 
97  forAll(bm, patchi)
98  {
99  const polyPatch& p = bm[patchi];
100 
101  if (isA<filmSurfacePolyPatch>(p))
102  {
103  if (surfacePatchID == -1)
104  {
106  }
107  else
108  {
110  << "More than one filmSurface patch defined: "
111  << surfacePatchID << " and " << patchi
112  << exit(FatalError);
113  }
114  }
115  }
116 
117  if (surfacePatchID == -1)
118  {
119  Info<< "The filmSurface patch is not defined"
120  << endl;
121  }
122 
123 
124  // Calculate film specific mesh geometry from the film wall patches
125 
126  forAll(wallPatchIDs, i)
127  {
128  const label patchi = wallPatchIDs[i];
129  const polyPatch& wallp = bm[patchi];
130  const labelList& fCells = wallp.faceCells();
131 
132  UIndirectList<vector>(nHat_, fCells) = wallp.faceNormals();
133  UIndirectList<scalar>(magSf_, fCells) = wallp.magFaceAreas();
134  }
135 
137 
140 
141  return true;
142 }
143 
144 
145 Foam::wordList Foam::solvers::isothermalFilm::alphaTypes() const
146 {
147  wordList alphaTypes(delta_.boundaryField().types());
148 
149  forAll(delta_.boundaryField(), patchi)
150  {
151  if (!delta_.boundaryField()[patchi].assignable())
152  {
154  }
155  }
156 
157  forAll(wallPatchIDs, i)
158  {
159  alphaTypes[wallPatchIDs[i]] = alphaOneFvPatchScalarField::typeName;
160  }
161 
162  if (surfacePatchID != -1)
163  {
164  alphaTypes[surfacePatchID] = alphaOneFvPatchScalarField::typeName;
165  }
166 
167  return alphaTypes;
168 }
169 
170 
171 void Foam::solvers::isothermalFilm::correctCoNum()
172 {
173  const scalarField sumPhi(fvc::surfaceSum(mag(phi))().primitiveField());
174 
175  CoNum = 0.5*gMax(sumPhi/mesh.V().primitiveField())*runTime.deltaTValue();
176 
177  const scalar meanCoNum =
178  0.5
179  *(gSum(sumPhi)/gSum(mesh.V().primitiveField()))
180  *runTime.deltaTValue();
181 
182  Info<< "Courant Number mean: " << meanCoNum
183  << " max: " << CoNum << endl;
184 }
185 
186 
187 void Foam::solvers::isothermalFilm::continuityErrors()
188 {
190 
191  correctContinuityError();
192 
193  if (mass.value() > small)
194  {
195  const volScalarField::Internal massContErr
196  (
197  runTime.deltaT()*magSf*contErr()
198  );
199 
200  const scalar sumLocalContErr =
201  (fvc::domainIntegrate(mag(massContErr))/mass).value();
202 
203  const scalar globalContErr =
204  (fvc::domainIntegrate(massContErr)/mass).value();
205 
206  Info<< "time step continuity errors : sum local = " << sumLocalContErr
207  << ", global = " << globalContErr;
208 
209  if (pimple.finalPisoIter() && pimple.finalIter())
210  {
212 
213  Info<< ", cumulative = " << cumulativeContErr;
214  }
215 
216  Info<< endl;
217  }
218 }
219 
220 
221 // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
222 
224 {
225  return runTime.controlDict().modified();
226 }
227 
228 
230 {
231  solver::read();
232 
233  maxCo =
234  runTime.controlDict().lookupOrDefault<scalar>("maxCo", vGreat);
235 
236  maxDeltaT_ =
237  runTime.controlDict().found("maxDeltaT")
238  ? runTime.controlDict().lookup<scalar>("maxDeltaT", runTime.userUnits())
239  : vGreat;
240 
241  return true;
242 }
243 
244 
245 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
246 
248 (
249  fvMesh& mesh,
250  autoPtr<rhoFluidThermo> thermoPtr
251 )
252 :
253  solver(mesh),
254 
255  CoNum(0),
257 
258  thermoPtr_(thermoPtr),
259  thermo_(thermoPtr_()),
260 
261  p(thermo_.p()),
262 
263  nHat_
264  (
265  IOobject
266  (
267  "nHat",
268  runTime.name(),
269  mesh
270  ),
271  mesh,
274  ),
275 
276  magSf_
277  (
278  IOobject
279  (
280  "magSf",
281  runTime.name(),
282  mesh
283  ),
284  mesh,
286  ),
287 
288  VbyA_
289  (
290  IOobject
291  (
292  "VbyA",
293  runTime.name(),
294  mesh
295  ),
296  mesh,
299  ),
300 
301  initialised_(initFilmMesh()),
302 
303  delta_
304  (
305  IOobject
306  (
307  "delta",
308  runTime.name(),
309  mesh,
310  IOobject::MUST_READ,
311  IOobject::AUTO_WRITE
312  ),
313  mesh,
314  dimensions::length
315  ),
316 
317  alpha_
318  (
319  IOobject
320  (
321  "alpha",
322  runTime.name(),
323  mesh,
324  IOobject::READ_IF_PRESENT,
325  IOobject::AUTO_WRITE
326  ),
327  delta_/VbyA_,
328  alphaTypes()
329  ),
330 
331  deltaWet("deltaWet", dimLength, thermo_.properties()),
332 
333  U_
334  (
335  IOobject
336  (
337  "U",
338  runTime.name(),
339  mesh,
340  IOobject::MUST_READ,
341  IOobject::AUTO_WRITE
342  ),
343  mesh,
344  dimensions::velocity
345  ),
346 
347  alphaRhoPhi_
348  (
349  IOobject
350  (
351  "alphaRhoPhi",
352  runTime.name(),
353  mesh,
354  IOobject::READ_IF_PRESENT,
355  IOobject::AUTO_WRITE
356  ),
357  fvc::flux(alpha_*thermo_.rho()*U_)
358  ),
359 
360  phi_
361  (
362  IOobject
363  (
364  "phi",
365  runTime.name(),
366  mesh,
367  IOobject::READ_IF_PRESENT,
368  IOobject::AUTO_WRITE
369  ),
370  fvc::flux(U_)
371  ),
372 
373  surfaceTension(surfaceTensionModel::New(thermo_.properties(), mesh)),
374  thermocapillary(!isType<surfaceTensionModels::constant>(surfaceTension())),
375 
376  g
377  (
378  IOobject
379  (
380  "g",
381  runTime.constant(),
382  mesh,
383  IOobject::MUST_READ,
384  IOobject::NO_WRITE
385  ),
386  dimensions::acceleration
387  ),
388 
389  nHat(nHat_),
390  magSf(magSf_),
391  VbyA(VbyA_),
392  delta(delta_),
393  alpha(alpha_),
394  thermo(thermo_),
395  rho(thermo_.rho()),
396  U(U_),
397  alphaRhoPhi(alphaRhoPhi_),
398  phi(phi_),
399 
400  momentumTransport
401  (
402  filmCompressible::momentumTransportModel::New
403  (
404  alpha,
405  thermo.rho(),
406  U,
407  alphaRhoPhi,
408  phi,
409  thermo
410  )
411  )
412 {
413  // Read the controls
414  read();
415 
417  momentumTransport->validate();
418 }
419 
420 
422 :
424 {}
425 
426 
427 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
428 
430 {}
431 
432 
433 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
434 
436 {
437  return mesh.boundary()[surfacePatchID];
438 }
439 
440 
443 {
444  return refCast<const mappedFvPatchBaseBase>(surfacePatch());
445 }
446 
447 
449 {
450  scalar deltaT = min(fvModels().maxDeltaT(), maxDeltaT_);
451 
452  if (CoNum > small)
453  {
454  deltaT = min(deltaT, maxCo/CoNum*runTime.deltaTValue());
455  }
456 
457  return deltaT;
458 }
459 
460 
462 {
463  correctCoNum();
464 }
465 
466 
468 {
469  continuityPredictor();
470 }
471 
472 
474 {
475  momentumTransport->predict();
476 }
477 
478 
480 {}
481 
482 
484 {}
485 
486 
488 {}
489 
490 
492 {
493  thermo_.correct();
494 }
495 
496 
498 {
499  correctAlpha();
500 }
501 
502 
504 {
505  momentumTransport->correct();
506 }
507 
508 
510 {}
511 
512 
514 {}
515 
516 
517 // ************************************************************************* //
scalar delta
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
Macros for easy insertion into run-time selection tables.
Internal::FieldType & primitiveFieldRef()
Return a reference to the primitive field.
DimensionedField< Type, GeoMesh, PrimitiveField > Internal
Type of the internal field from which this GeometricField is derived.
void correctBoundaryConditions()
Correct boundary field.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
const word & name() const
Return name.
Definition: IOobject.H:307
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:342
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:98
const DimensionedField< scalar, fvMesh > & V() const
Return cell volumes.
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:934
const fvSchemes & schemes() const
Return the fvSchemes.
Definition: fvMesh.C:1795
const polyMesh & poly() const
Return reference to polyMesh.
Definition: fvMesh.H:456
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:58
void setFluxRequired(const word &name) const
Definition: fvSchemes.C:434
Base class for fv patches that provide mapping between two fv patches.
Abstract base class for momentum transport models (RAS, LES and laminar).
const polyBoundaryMesh & boundary() const
Return boundary mesh.
Definition: polyMesh.H:393
label nCells() const
Base-class for fluid thermodynamic properties based on density.
Abstract base class for run-time selectable region solvers.
Definition: solver.H:56
const fvMesh & mesh
Region mesh.
Definition: solver.H:101
virtual bool read()
Read controls.
Definition: solver.C:52
Solver module for flow of compressible isothermal liquid films.
virtual void thermophysicalPredictor()
Construct and solve the energy equation,.
virtual void momentumTransportCorrector()
Correct the momentum transport.
virtual void prePredictor()
Called at the start of the PIMPLE loop.
virtual void postSolve()
Called after the PIMPLE loop at the end of the time-step.
volScalarField & p
The thermodynamic pressure field.
virtual void momentumTransportPredictor()
Predict the momentum transport.
autoPtr< filmCompressible::momentumTransportModel > momentumTransport
Pointer to the momentum transport model.
virtual bool dependenciesModified() const
Return true if the solver's dependencies have been modified.
const volScalarField & alpha
Film volume fraction in the cell layer.
virtual void moveMesh()
Called at the start of the PIMPLE loop to move the mesh.
virtual scalar maxDeltaT() const
Return the current maximum time-step for stable solution.
virtual void motionCorrector()
Corrections that follow mesh motion.
virtual void pressureCorrector()
Construct and solve the pressure equation in the PISO loop.
isothermalFilm(fvMesh &mesh, autoPtr< rhoFluidThermo >)
Construct from region mesh and thermophysical properties.
volScalarField VbyA_
Film cell volume/wall face area.
const mappedFvPatchBaseBase & surfacePatchMap() const
Return the film surface patch region-region map.
const fvPatch & surfacePatch() const
Return the film surface patch.
virtual void thermophysicalTransportCorrector()
Correct the thermophysical transport.
volScalarField::Internal magSf_
Film cell cross-sectional area magnitude.
volVectorField nHat_
Film wall normal.
virtual void preSolve()
Called at the start of the time-step, before the PIMPLE loop.
label surfacePatchID
Film surface patch ID.
virtual ~isothermalFilm()
Destructor.
virtual void thermophysicalTransportPredictor()
Predict thermophysical transport.
virtual bool read()
Read controls.
labelList wallPatchIDs
List of film wall patch IDs.
'Patch' on surface as subset of triSurface.
Definition: surfacePatch.H:61
Abstract base-class for surface tension models which return the surface tension coefficient field.
Template function which returns the un-mangled name of a given type. Useful for types which do not ha...
This boundary condition applies a zero-gradient condition from the patch internal field onto the patc...
scalar CoNum
scalar meanCoNum
Foam::fvModels & fvModels(Foam::fvModels::New(mesh))
pimpleControl pimple(mesh)
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
scalar maxDeltaT
scalar maxCo
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
Calculate the first temporal derivative.
Calculate the divergence of the given field.
Calculate the face-flux of the given field.
Surface integrate surfaceField creating a volField. Surface sum a surfaceField creating a volField.
Volume integrate volField creating a volField.
label patchi
scalar cumulativeContErr
label nWallFaces(0)
U
Definition: pEqn.H:72
rho
Definition: pEqn.H:1
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
const dimensionSet velocity
const dimensionSet dimless
const dimensionSet mass
const dimensionSet acceleration
const dimensionSet length
dimensioned< Type > domainIntegrate(const VolField< Type > &vf)
tmp< VolInternalField< Type > > surfaceSum(const SurfaceField< Type > &ssf)
addToRunTimeSelectionTable(solver, compressibleMultiphaseVoF, fvMesh)
defineTypeNameAndDebug(basicFluidSolver, 0)
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
static const zero Zero
Definition: zero.H:97
List< word > wordList
A List of words.
Definition: fileName.H:54
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
const dimensionSet & dimLength
Definition: dimensions.C:276
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
bool isType(const Type &t)
Check the typeid.
Definition: typeInfo.H:170
messageStream Info
Type gSum(const UList< Type > &f, const label comm)
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
Type gMax(const UList< Type > &f, const label comm)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
error FatalError
const dimensionSet & dimArea
Definition: dimensions.C:281
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
volScalarField & p
fluidMulticomponentThermo & thermo
Definition: createFields.H:15
scalar sumLocalContErr
Definition: volContinuity.H:9
scalar globalContErr
Definition: volContinuity.H:12