setWaves.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) 2017-2018 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 Application
25  setWaves
26 
27 Description
28  Applies wave models to the entire domain for case initialisation using
29  level sets for second-order accuracy.
30 
31 \*---------------------------------------------------------------------------*/
32 
33 #include "fvCFD.H"
34 #include "levelSet.H"
35 #include "pointFields.H"
36 #include "timeSelector.H"
37 #include "wallDist.H"
40 #include "waveSuperposition.H"
41 
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 
44 int main(int argc, char *argv[])
45 {
46  timeSelector::addOptions(false, false);
47 
49  (
50  "U",
51  "name",
52  "name of the velocity field, default is \"U\""
53  );
54 
56  (
57  "alpha",
58  "name",
59  "name of the volume fraction field, default is \"alpha\""
60  );
61 
62  #include "setRootCase.H"
63  #include "createTime.H"
64 
65  instantList timeDirs = timeSelector::selectIfPresent(runTime, args);
66 
67  #include "createMesh.H"
68  #include "readGravitationalAcceleration.H"
69 
70  const pointMesh& pMesh = pointMesh::New(mesh);
71 
72  forAll(timeDirs, timeI)
73  {
74  runTime.setTime(timeDirs[timeI], timeI);
75  const scalar t = runTime.value();
76 
77  Info<< "Time = " << runTime.timeName() << nl << endl;
78 
79  mesh.readUpdate();
80 
81  // Read the fields which are to be set
83  (
84  IOobject
85  (
86  args.optionFound("alpha") ? args["alpha"] : "alpha",
87  runTime.timeName(),
88  mesh,
89  IOobject::MUST_READ
90  ),
91  mesh
92  );
94  (
95  IOobject
96  (
97  args.optionFound("U") ? args["U"] : "U",
98  runTime.timeName(),
99  mesh,
100  IOobject::MUST_READ
101  ),
102  mesh
103  );
104 
105  // Create modelled fields on both cells and points
107  (
108  IOobject("h", runTime.timeName(), mesh),
109  mesh,
111  );
113  (
114  IOobject("hp", runTime.timeName(), mesh),
115  pMesh,
117  );
118  volVectorField uGas
119  (
120  IOobject("uGas", runTime.timeName(), mesh),
121  mesh,
122  dimensionedVector("0", dimVelocity, vector::zero)
123  );
124  pointVectorField uGasp
125  (
126  IOobject("uGasp", runTime.timeName(), mesh),
127  pMesh,
128  dimensionedVector("0", dimLength, vector::zero)
129  );
130  volVectorField uLiq
131  (
132  IOobject("uLiq", runTime.timeName(), mesh),
133  mesh,
134  dimensionedVector("0", dimVelocity, vector::zero)
135  );
136  pointVectorField uLiqp
137  (
138  IOobject("uLiqp", runTime.timeName(), mesh),
139  pMesh,
140  dimensionedVector("0", dimLength, vector::zero)
141  );
142 
143  // The number of wave patches
144  label nWaves = 0;
145 
146  // Whether the alpha conditions refer to the liquid phase
147  bool liquid = false;
148 
149  // Loop the patches, averaging and superimposing wave model data
150  forAll(mesh.boundary(), patchi)
151  {
152  fvPatchScalarField& alphap = alpha.boundaryFieldRef()[patchi];
153  fvPatchVectorField& Up = U.boundaryFieldRef()[patchi];
154 
155  const bool isWave = isA<waveAlphaFvPatchScalarField>(alphap);
156 
157  if (isA<waveVelocityFvPatchVectorField>(Up) != isWave)
158  {
160  << "The alpha condition on patch " << Up.patch().name()
161  << " is " << alphap.type() << " and the velocity condition"
162  << " is " << Up.type() << ". Wave boundary conditions must"
163  << " be set in pairs. If the alpha condition is "
164  << waveAlphaFvPatchScalarField::typeName
165  << " then the velocity condition must be "
166  << waveVelocityFvPatchVectorField::typeName
167  << " and vice-versa." << exit(FatalError);
168  }
169 
170  if (!isWave)
171  {
172  continue;
173  }
174 
175  Info<< "Adding waves from patch " << Up.patch().name() << endl;
176 
177  const waveSuperposition& waves =
178  refCast<waveVelocityFvPatchVectorField>(Up).waves();
179 
180  const bool liquidp =
181  refCast<waveAlphaFvPatchScalarField>(alphap).liquid();
182  if (nWaves > 0 && liquidp != liquid)
183  {
185  << "All " << waveAlphaFvPatchScalarField::typeName
186  << "patch fields must be configured for the same phase,"
187  << " i.e., the liquid switch must have the same value."
188  << exit(FatalError);
189  }
190  liquid = liquidp;
191 
192  const pointField& ccs = mesh.cellCentres();
193  const pointField& pts = mesh.points();
194 
195  // Internal field superposition
196  h.primitiveFieldRef() += waves.height(t, ccs);
197  hp.primitiveFieldRef() += waves.height(t, pts);
198  uGas.primitiveFieldRef() += waves.UGas(t, ccs) - waves.UMean(t);
199  uGasp.primitiveFieldRef() += waves.UGas(t, pts) - waves.UMean(t);
200  uLiq.primitiveFieldRef() += waves.ULiquid(t, ccs) - waves.UMean(t);
201  uLiqp.primitiveFieldRef() += waves.ULiquid(t, pts) - waves.UMean(t);
202 
203  // Boundary field superposition
204  forAll(mesh.boundary(), patchj)
205  {
206  const pointField& fcs = mesh.boundary()[patchj].Cf();
207  h.boundaryFieldRef()[patchj] += waves.height(t, fcs);
208  uGas.boundaryFieldRef()[patchj] +=
209  waves.UGas(t, fcs) - waves.UMean(t);
210  uLiq.boundaryFieldRef()[patchj] +=
211  waves.ULiquid(t, fcs) - waves.UMean(t);
212  }
213 
214  ++ nWaves;
215  }
216 
217  // Create the mean velocity field
219  (
220  IOobject("UMean", runTime.timeName(), mesh),
221  mesh,
223  );
224 
225  if (nWaves == 0)
226  {
227  // Warn and skip to the next time if there are no wave patches
229  << "No " << waveAlphaFvPatchScalarField::typeName << " or "
230  << waveVelocityFvPatchVectorField::typeName << " patch fields "
231  << "were found. No waves have been set." << endl;
232 
233  continue;
234  }
235  else if (nWaves == 1)
236  {
237  // Set a mean velocity equal to that on the only wave patch
238  forAll(mesh.boundary(), patchi)
239  {
240  const fvPatchVectorField& Up = U.boundaryField()[patchi];
241  if (!isA<waveVelocityFvPatchVectorField>(Up))
242  {
243  continue;
244  }
245 
246  const waveSuperposition& waves =
247  refCast<const waveVelocityFvPatchVectorField>(Up).waves();
248 
249  UMean ==
250  dimensionedVector("UMean", dimVelocity, waves.UMean(t));
251  }
252  }
253  else if (nWaves > 1)
254  {
255  // Set the mean velocity by distance weighting from the wave patches
256 
257  // Create weighted average fields for the mean velocity
258  volScalarField weight
259  (
260  IOobject("weight", runTime.timeName(), mesh),
261  mesh,
263  );
264  volVectorField weightUMean
265  (
266  IOobject("weightUMean", runTime.timeName(), mesh),
267  mesh,
268  dimensionedVector("0", dimVelocity/dimLength, vector::zero)
269  );
270 
271  // Loop the patches, inverse-distance weighting the mean velocities
272  forAll(mesh.boundary(), patchi)
273  {
274  const fvPatchVectorField& Up = U.boundaryField()[patchi];
275  if (!isA<waveVelocityFvPatchVectorField>(Up))
276  {
277  continue;
278  }
279 
280  const waveSuperposition& waves =
281  refCast<const waveVelocityFvPatchVectorField>(Up).waves();
282 
283  const volScalarField w
284  (
285  1
286  /(
287  wallDist(mesh, labelList(1, patchi)).y()
288  + dimensionedScalar("ySmall", dimLength, small)
289  )
290  );
291 
292  weight += w;
293  weightUMean +=
294  w*dimensionedVector("wUMean", dimVelocity, waves.UMean(t));
295  }
296 
297  // Complete the average for the mean velocity
298  UMean = weightUMean/weight;
299  }
300 
301  // Set the fields
302  alpha == levelSetFraction(h, hp, !liquid);
303  U == UMean + levelSetAverage(h, hp, uGas, uGasp, uLiq, uLiqp);
304 
305  // Set the boundary fields
306  forAll(mesh.boundary(), patchi)
307  {
308  fvPatchScalarField& alphap = alpha.boundaryFieldRef()[patchi];
309  fvPatchVectorField& Up = U.boundaryFieldRef()[patchi];
310  if (isA<waveAlphaFvPatchScalarField>(alphap))
311  {
312  alphap == refCast<waveAlphaFvPatchScalarField>(alphap).alpha();
313  Up == refCast<waveVelocityFvPatchVectorField>(Up).U();
314  }
315  }
316 
317  // Output
318  Info<< "Writing " << alpha.name() << nl;
319  alpha.write();
320  Info<< "Writing " << U.name() << nl << endl;
321  U.write();
322  }
323 
324  Info<< "End\n" << endl;
325 
326  return 0;
327 }
328 
329 
330 // ************************************************************************* //
GeometricField< scalar, pointPatchField, pointMesh > pointScalarField
Definition: pointFields.H:49
List< instant > instantList
List of instants.
Definition: instantList.H:42
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
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
fvPatchField< vector > fvPatchVectorField
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
tmp< scalarField > levelSetFraction(const fvMesh &mesh, const scalarField &levelC, const scalarField &levelP, const bool above)
Calculate the volume-fraction that a level set occupies. This gives the.
Definition: levelSet.C:34
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:256
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:108
volVectorField UMean(UMeanHeader, mesh)
GeometricField< vector, fvPatchField, volMesh > volVectorField
Definition: volFieldsFwd.H:55
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:52
scalar y
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
dynamicFvMesh & mesh
fvPatchField< scalar > fvPatchScalarField
static void addOption(const word &opt, const string &param="", const string &usage="")
Add to an option to validOptions with usage information.
Definition: argList.C:120
List< label > labelList
A List of labels.
Definition: labelList.H:56
static const zero Zero
Definition: zero.H:97
static const char nl
Definition: Ostream.H:265
tmp< Field< Type > > levelSetAverage(const fvMesh &mesh, const scalarField &levelC, const scalarField &levelP, const Field< Type > &positiveC, const Field< Type > &positiveP, const Field< Type > &negativeC, const Field< Type > &negativeP)
Calculate the average value of two fields, one on each side of a level set.
const word & name() const
Return const reference to name.
label patchi
U
Definition: pEqn.H:72
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:47
volScalarField & h
Planck constant.
#define WarningInFunction
Report a warning using Foam::Warning.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
GeometricField< vector, pointPatchField, pointMesh > pointVectorField
Definition: pointFields.H:50
messageStream Info
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
Foam::argList args(argc, argv)
const dimensionSet dimVelocity