irregular.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-2024 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 "irregular.H"
27 #include "mathematicalConstants.H"
28 #include "OSspecific.H"
29 #include "randomGenerator.H"
30 #include "rawSetWriter.H"
31 #include "writeFile.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38 namespace waveModels
39 {
42 }
43 }
44 
45 
46 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
47 
49 Foam::waveModels::irregular::coeffs(const label i) const
50 {
51  return AiryCoeffs(depth_, amplitudes_[i], lengths_[i], g());
52 }
53 
54 
55 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
56 
58 :
59  waveModel(wave),
60  depth_(wave.depth_),
61  spectrum_(wave.spectrum_, false),
62  n_(wave.n_),
63  span_(wave.span_),
64  formatter_(wave.formatter_, false),
65  amplitudes_(wave.amplitudes_),
66  lengths_(wave.lengths_),
67  phases_(wave.phases_)
68 {}
69 
70 
72 (
73  const dictionary& dict,
74  const scalar g,
75  const word& modelName
76 )
77 :
78  waveModel(dict, g),
79  depth_(dict.lookupOrDefault<scalar>("depth", great)),
80  spectrum_(waveSpectrum::New(dict, g)),
81  n_(dict.lookup<label>("n")),
82  span_(dict.lookupOrDefault("span", Pair<scalar>(0.01, 0.99))),
83  formatter_
84  (
85  dict.found("setFormat")
86  ? setWriter::New(dict.lookup("setFormat"), dict).ptr()
87  : nullptr
88  ),
89  amplitudes_(n_),
90  lengths_(n_),
91  phases_(n_)
92 {
93  // Get the bounds of the frequency space
94  const Pair<scalar> f01
95  (
96  spectrum_->fFraction(span_.first()),
97  spectrum_->fFraction(span_.second())
98  );
99 
100  // Create a discretisation in frequency space
101  const scalarField x(scalarField(scalarList(identityMap(n_ + 1)))/n_);
102  const scalarField f((1 - x)*f01.first() + x*f01.second());
103 
104  // Evaluate the integrals of the distribution
105  const scalarField integralS(spectrum_->integralS(f));
106  const scalarField integralFS(spectrum_->integralFS(f));
107 
108  // Set the wave parameters using means constructed from the integrals over
109  // the frequency intervals
110  scalarList periods(n_);
111  forAll(amplitudes_, i)
112  {
113  const label j0 = n_ - 1 - i, j1 = n_ - i;
114 
115  // Integrating the of power spectral density gives the square of the
116  // root-mean-squared value. So, a factor of two is needed to convert to
117  // peak amplitude.
118  amplitudes_[i] = sqrt(2*(integralS[j1] - integralS[j0]));
119 
120  // Frequency is the integrated average, Integral(f*S)/Integral(S), for
121  // this interval. Period is the reciprocal of this value.
122  periods[i] =
123  (integralS[j1] - integralS[j0])/(integralFS[j1] - integralFS[j0]);
124 
125  // Let the Airy calculation engine convert the above to wavelength
126  lengths_[i] =
127  AiryCoeffs
128  (
129  depth_,
130  amplitudes_[i],
131  periods[i],
132  g,
134  ).length;
135  }
136 
137  // Set random phases
138  randomGenerator rndGen(0, true);
139  forAll(phases_, i)
140  {
141  phases_[i] = rndGen.scalarAB(0, constant::mathematical::twoPi);
142  }
143 
144  // Report
145  const scalar avgAmplitude =
146  sqrt(2*(integralS.last() - integralS.first())/(f.last() - f.first()));
147  const scalar avgPeroid =
148  (integralS.last() - integralS.first())
149  /(integralFS.last() - integralFS.first());
150  const scalar avgLength =
151  AiryCoeffs(depth_, avgAmplitude, avgPeroid, g, AiryCoeffs::celerity)
152  .length;
153  const string::size_type pad =
154  waveModel::typeName.length() + modelName.length() + 2;
155  Info<< waveModel::typeName << ": " << modelName
156  << ": min/average/max period = "
157  << periods.first() << '/' << avgPeroid << '/' << periods.last()
158  << endl << string(pad, ' ').c_str()
159  << " min/average/max length = "
160  << lengths_.first() << '/' << avgLength << '/' << lengths_.last()
161  << endl;
162 
163  // Write out the continuous distribution
164  if (Pstream::master() && formatter_.valid())
165  {
166  static const scalar t = 0.1;
167 
168  const Pair<scalar> g01
169  (
170  max(rootVSmall, (1 + t)*(f01.first() - t*f01.second())),
171  - t*f01.first() + (1 + t)*f01.second()
172  );
173 
174  const label nn = 1024;
175  const scalarField xx(scalarField(scalarList(identityMap(nn + 1)))/nn);
176  const scalarField ff((1 - xx)*g01.first() + xx*g01.second());
177 
178  formatter_->write
179  (
180  cwd()
182  /waveModel::typeName + "s"
183  /modelName + spectrum_->type().capitalise(),
184  "continuous",
185  coordSet(true, "f", ff),
186  "S",
187  spectrum_->S(ff)()
188  );
189  }
190 
191  // Write out the sampled distribution
192  if (Pstream::master() && formatter_.valid())
193  {
194  scalarField ff(3*n_ + 1), SS(3*n_ + 1);
195 
196  forAll(f, i)
197  {
198  if (i != 0)
199  {
200  ff[3*i - 1] = f[i];
201  SS[3*i - 1] = sqr(amplitudes_[n_ - i])/2/(f[i] - f[i - 1]);
202  }
203 
204  ff[3*i] = f[i];
205  SS[3*i] = 0;
206 
207  if (i != n_)
208  {
209  ff[3*i + 1] = f[i];
210  SS[3*i + 1] = sqr(amplitudes_[n_ - 1 - i])/2/(f[i + 1] - f[i]);
211  }
212  }
213 
214  formatter_->write
215  (
216  cwd()
218  /waveModel::typeName + "s"
219  /modelName + spectrum_->type().capitalise(),
220  "sampled",
221  coordSet(true, "f", ff),
222  "S",
223  SS
224  );
225  }
226 }
227 
228 
229 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
230 
232 {}
233 
234 
235 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
236 
238 {
239  return coeffs(amplitudes_.size() - 1).celerity();
240 }
241 
242 
244 (
245  const scalar t,
246  const scalarField& x
247 ) const
248 {
249  tmp<scalarField> tResult(new scalarField(x.size(), scalar(0)));
250  scalarField& result = tResult.ref();
251 
252  forAll(amplitudes_, i)
253  {
254  result += coeffs(i).elevation(phases_[i], t, x);
255  }
256 
257  return tResult;
258 }
259 
260 
262 (
263  const scalar t,
264  const vector2DField& xz
265 ) const
266 {
268  vector2DField& result = tResult.ref();
269 
270  forAll(amplitudes_, i)
271  {
272  result += coeffs(i).velocity(phases_[i], t, xz);
273  }
274 
275  return tResult;
276 }
277 
278 
280 {
281  waveModel::write(os);
282 
283  if (!coeffs(amplitudes_.size() - 1).deep())
284  {
285  writeEntry(os, "depth", depth_);
286  }
287 
288  writeEntry(os, "spectrum", spectrum_->type());
289 
290  os << indent << word(spectrum_->type() + "Coeffs") << nl
292  spectrum_->write(os);
293  os << decrIndent
294  << indent << token::END_BLOCK << nl;
295 
296  writeEntry(os, "n", n_);
297  writeEntryIfDifferent(os, "span", Pair<scalar>(0.01, 0.99), span_);
298 }
299 
300 
301 // ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:73
bool found
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
Macros for easy insertion into run-time selection tables.
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
virtual Ostream & write(const char)=0
Write character.
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: Pair.H:65
const Type & second() const
Return second.
Definition: Pair.H:110
const Type & first() const
Return first.
Definition: Pair.H:98
T & first()
Return the first element of the list.
Definition: UListI.H:114
T & last()
Return the last element of the list.
Definition: UListI.H:128
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:423
static const Form zero
Definition: VectorSpace.H:118
Holds list of sampling positions.
Definition: coordSet.H:51
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:162
static const word outputPrefix
Directory prefix.
Definition: writeFile.H:72
Random number generator.
Base class for writing coordinate sets with data.
Definition: setWriter.H:64
A class for handling character strings derived from std::string.
Definition: string.H:79
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:181
@ BEGIN_BLOCK
Definition: token.H:113
@ END_BLOCK
Definition: token.H:114
Generic base class for waves. Derived classes must implement field functions which return the elevati...
Definition: waveModel.H:56
scalar g() const
Get the value of gravity.
Definition: waveModel.H:117
virtual void write(Ostream &os) const
Write.
Definition: waveModel.C:59
Calculation engine for the Airy wave model and other models that are a correction on top of the Airy ...
Definition: AiryCoeffs.H:52
scalar celerity() const
The wave celerity [m/s].
Definition: AiryCoeffs.C:111
const scalar length
Wavelength [m].
Definition: AiryCoeffs.H:82
Irregular wave model. Phase fraction and velocity field are built up from multiple first-order waves,...
Definition: irregular.H:116
virtual scalar celerity() const
The wave celerity [m/s].
Definition: irregular.C:237
virtual tmp< scalarField > elevation(const scalar t, const scalarField &x) const
Get the wave elevation at a given time and local coordinates. Local.
Definition: irregular.C:244
virtual void write(Ostream &os) const
Write.
Definition: irregular.C:279
irregular(const irregular &wave)
Construct a copy.
Definition: irregular.C:57
virtual tmp< vector2DField > velocity(const scalar t, const vector2DField &xz) const
Get the wave velocity at a given time and local coordinates. Local.
Definition: irregular.C:262
virtual ~irregular()
Destructor.
Definition: irregular.C:231
Base class for wave spectra.
Definition: waveSpectrum.H:50
A class for handling words, derived from string.
Definition: word.H:62
const scalar twoPi(2 *pi)
label wave(const fvMesh &mesh, const List< labelPair > &changedPatchAndFaces, const label nCorrections, GeometricField< scalar, PatchField, GeoMesh > &distance, TrackingData &td, GeometricField< DataType, PatchField, GeoMesh > &... data)
Wave distance (and maybe additional) data from faces. If nCorrections is.
const FieldField< fvPatchField, Type > & ff(const FieldField< fvPatchField, Type > &bf)
defineTypeNameAndDebug(Airy, 0)
addToRunTimeSelectionTable(waveModel, Airy, dictionary)
Namespace for OpenFOAM.
fileName cwd()
Return current working directory path name.
Definition: POSIX.C:241
void writeEntryIfDifferent(Ostream &os, const word &entryName, const EntryType &value1, const EntryType &value2)
Helper function to write the keyword and entry only if the.
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:241
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
dimensionedSymmTensor sqr(const dimensionedVector &dv)
dimensionedScalar j1(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:257
messageStream Info
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:234
List< scalar > scalarList
A List of scalars.
Definition: scalarList.H:50
Field< vector2D > vector2DField
Forward declarations of the specialisation of Field<T> for vector2D.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
void writeEntry(Ostream &os, const HashTable< T, Key, Hash > &ht)
Definition: HashTableIO.C:96
dimensionedScalar sqrt(const dimensionedScalar &ds)
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:227
static const char nl
Definition: Ostream.H:266
dimensionedScalar j0(const dimensionedScalar &ds)
labelList f(nPoints)
dictionary dict
randomGenerator rndGen(653213)