forceCoeffs.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-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2020 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 "forceCoeffs.H"
30 #include "dictionary.H"
31 #include "Time.H"
32 #include "Pstream.H"
33 #include "IOmanip.H"
34 #include "fvMesh.H"
35 #include "dimensionedTypes.H"
36 #include "volFields.H"
38 
39 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43 namespace functionObjects
44 {
45  defineTypeNameAndDebug(forceCoeffs, 0);
46  addToRunTimeSelectionTable(functionObject, forceCoeffs, dictionary);
47 }
48 }
49 
50 
51 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
52 
54 {
55  // Note: Only possible to create bin files after bins have been initialised
56 
57  if (writeToFile() && !coeffFilePtr_)
58  {
59  coeffFilePtr_ = createFile("coefficient");
60  writeIntegratedHeader("Coefficients", coeffFilePtr_());
61 
62  if (nBin_ > 1)
63  {
64  CdBinFilePtr_ = createFile("CdBin");
65  writeBinHeader("Drag coefficient bins", CdBinFilePtr_());
66 
67  CsBinFilePtr_ = createFile("CsBin");
68  writeBinHeader("Side coefficient bins", CsBinFilePtr_());
69 
70  ClBinFilePtr_ = createFile("ClBin");
71  writeBinHeader("Lift coefficient bins", ClBinFilePtr_());
72 
73  CmRollBinFilePtr_ = createFile("CmRollBin");
74  writeBinHeader("Roll moment coefficient bins", CmRollBinFilePtr_());
75 
76  CmPitchBinFilePtr_ = createFile("CmPitchBin");
77  writeBinHeader("Moment coefficient bins", CmPitchBinFilePtr_());
78 
79  CmYawBinFilePtr_ = createFile("CmYawBin");
80  writeBinHeader("Yaw moment coefficient bins", CmYawBinFilePtr_());
81  }
82  }
83 }
84 
85 
87 (
88  const word& header,
89  Ostream& os
90 ) const
91 {
92  writeHeader(os, "Force coefficients");
93  writeHeaderValue(os, "dragDir", coordSys_.e1());
94  writeHeaderValue(os, "sideDir", coordSys_.e2());
95  writeHeaderValue(os, "liftDir", coordSys_.e3());
96  writeHeaderValue(os, "rollAxis", coordSys_.e1());
97  writeHeaderValue(os, "pitchAxis", coordSys_.e2());
98  writeHeaderValue(os, "yawAxis", coordSys_.e3());
99  writeHeaderValue(os, "magUInf", magUInf_);
100  writeHeaderValue(os, "lRef", lRef_);
101  writeHeaderValue(os, "Aref", Aref_);
102  writeHeaderValue(os, "CofR", coordSys_.origin());
103  writeHeader(os, "");
104  writeCommented(os, "Time");
105  writeTabbed(os, "Cd");
106  writeTabbed(os, "Cs");
107  writeTabbed(os, "Cl");
108  writeTabbed(os, "CmRoll");
109  writeTabbed(os, "CmPitch");
110  writeTabbed(os, "CmYaw");
111  writeTabbed(os, "Cd(f)");
112  writeTabbed(os, "Cd(r)");
113  writeTabbed(os, "Cs(f)");
114  writeTabbed(os, "Cs(r)");
115  writeTabbed(os, "Cl(f)");
116  writeTabbed(os, "Cl(r)");
117  os << endl;
118 }
119 
120 
122 (
123  const word& header,
124  Ostream& os
125 ) const
126 {
127  writeHeader(os, header);
128  writeHeaderValue(os, "bins", nBin_);
129  writeHeaderValue(os, "start", binMin_);
130  writeHeaderValue(os, "delta", binDx_);
131  writeHeaderValue(os, "direction", binDir_);
132 
133  vectorField binPoints(nBin_);
134  writeCommented(os, "x co-ords :");
135  forAll(binPoints, pointi)
136  {
137  binPoints[pointi] = (binMin_ + (pointi + 1)*binDx_)*binDir_;
138  os << tab << binPoints[pointi].x();
139  }
140  os << nl;
141 
142  writeCommented(os, "y co-ords :");
143  forAll(binPoints, pointi)
144  {
145  os << tab << binPoints[pointi].y();
146  }
147  os << nl;
148 
149  writeCommented(os, "z co-ords :");
150  forAll(binPoints, pointi)
151  {
152  os << tab << binPoints[pointi].z();
153  }
154  os << nl;
155 
156  writeHeader(os, "");
157  writeCommented(os, "Time");
158 
159  for (label j = 0; j < nBin_; ++j)
160  {
161  const word jn(Foam::name(j) + ':');
162  writeTabbed(os, jn + "total");
163  writeTabbed(os, jn + "pressure");
164  writeTabbed(os, jn + "viscous");
165 
166  if (porosity_)
167  {
168  writeTabbed(os, jn + "porous");
169  }
170  }
171 
172  os << endl;
173 }
174 
175 
177 (
178  const word& title,
179  const List<Field<scalar>>& coeff
180 ) const
181 {
182  if (!log)
183  {
184  return;
185  }
186 
187  const scalar pressure = sum(coeff[0]);
188  const scalar viscous = sum(coeff[1]);
189  const scalar porous = sum(coeff[2]);
190  const scalar total = pressure + viscous + porous;
191 
192  Info<< " " << title << " : " << total << token::TAB
193  << '('
194  << "pressure: " << pressure << token::TAB
195  << "viscous: " << viscous;
196 
197  if (porosity_)
198  {
199  Info<< token::TAB << "porous: " << porous;
200  }
201 
202  Info<< ')' << endl;
203 }
204 
205 
207 (
208  const List<Field<scalar>> coeffs,
209  Ostream& os
210 ) const
211 {
212  writeCurrentTime(os);
213 
214  for (label bini = 0; bini < nBin_; ++bini)
215  {
216  scalar total = coeffs[0][bini] + coeffs[1][bini] + coeffs[2][bini];
217 
218  os << tab << total << tab << coeffs[0][bini] << tab << coeffs[1][bini];
219 
220  if (porosity_)
221  {
222  os << tab << coeffs[2][bini];
223  }
224  }
225 
226  os << endl;
227 }
228 
229 
230 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
231 
232 Foam::functionObjects::forceCoeffs::forceCoeffs
233 (
234  const word& name,
235  const Time& runTime,
236  const dictionary& dict,
237  const bool readFields
238 )
239 :
240  forces(name, runTime, dict, false),
241  magUInf_(Zero),
242  lRef_(Zero),
243  Aref_(Zero),
244  coeffFilePtr_(),
245  CdBinFilePtr_(),
246  CsBinFilePtr_(),
247  ClBinFilePtr_(),
248  CmRollBinFilePtr_(),
249  CmPitchBinFilePtr_(),
250  CmYawBinFilePtr_()
251 {
252  if (readFields)
253  {
254  read(dict);
255  setCoordinateSystem(dict, "liftDir", "dragDir");
256  Info<< endl;
257  }
258 }
259 
260 
261 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
262 
264 {
266 
267  // Free stream velocity magnitude
268  dict.readEntry("magUInf", magUInf_);
269 
270  // If case is compressible we must read rhoInf (store in rhoRef_) to
271  // calculate the reference dynamic pressure
272  // Note: for incompressible, rhoRef_ is already initialised
273  if (rhoName_ != "rhoInf")
274  {
275  dict.readEntry("rhoInf", rhoRef_);
276  }
277 
278  // Reference length and area scales
279  dict.readEntry("lRef", lRef_);
280  dict.readEntry("Aref", Aref_);
281 
282  if (writeFields_)
283  {
284  volVectorField* forceCoeffPtr
285  (
286  new volVectorField
287  (
288  IOobject
289  (
290  fieldName("forceCoeff"),
291  mesh_.time().timeName(),
292  mesh_,
295  ),
296  mesh_,
298  )
299  );
300 
301  mesh_.objectRegistry::store(forceCoeffPtr);
302 
303  volVectorField* momentCoeffPtr
304  (
305  new volVectorField
306  (
307  IOobject
308  (
309  fieldName("momentCoeff"),
310  mesh_.time().timeName(),
311  mesh_,
314  ),
315  mesh_,
317  )
318  );
319 
320  mesh_.objectRegistry::store(momentCoeffPtr);
321  }
322 
323  return true;
324 }
325 
326 
328 {
330 
331  createFiles();
332 
333  // Storage for pressure, viscous and porous contributions to coeffs
335  List<Field<scalar>> sideCoeffs(3);
336  List<Field<scalar>> liftCoeffs(3);
337  List<Field<scalar>> rollMomentCoeffs(3);
338  List<Field<scalar>> pitchMomentCoeffs(3);
339  List<Field<scalar>> yawMomentCoeffs(3);
340 
341  forAll(liftCoeffs, i)
342  {
343  dragCoeffs[i].setSize(nBin_);
344  sideCoeffs[i].setSize(nBin_);
345  liftCoeffs[i].setSize(nBin_);
346  rollMomentCoeffs[i].setSize(nBin_);
347  pitchMomentCoeffs[i].setSize(nBin_);
348  yawMomentCoeffs[i].setSize(nBin_);
349  }
350 
351  // Calculate coefficients
352  scalar CdTot = 0;
353  scalar CsTot = 0;
354  scalar ClTot = 0;
355  scalar CmRollTot = 0;
356  scalar CmPitchTot = 0;
357  scalar CmYawTot = 0;
358 
359  const scalar pDyn = 0.5*rhoRef_*sqr(magUInf_);
360 
361  // Avoid divide by zero in 2D cases
362  const scalar momentScaling = 1.0/(Aref_*pDyn*lRef_ + SMALL);
363  const scalar forceScaling = 1.0/(Aref_*pDyn + SMALL);
364 
365  forAll(liftCoeffs, i)
366  {
367  const Field<vector> localForce(coordSys_.localVector(force_[i]));
368  const Field<vector> localMoment(coordSys_.localVector(moment_[i]));
369 
370  dragCoeffs[i] = forceScaling*(localForce.component(0));
371  sideCoeffs[i] = forceScaling*(localForce.component(1));
372  liftCoeffs[i] = forceScaling*(localForce.component(2));
373  rollMomentCoeffs[i] = momentScaling*(localMoment.component(0));
374  pitchMomentCoeffs[i] = momentScaling*(localMoment.component(1));
375  yawMomentCoeffs[i] = momentScaling*(localMoment.component(2));
376 
377  CdTot += sum(dragCoeffs[i]);
378  CsTot += sum(sideCoeffs[i]);
379  ClTot += sum(liftCoeffs[i]);
380  CmRollTot += sum(rollMomentCoeffs[i]);
381  CmPitchTot += sum(pitchMomentCoeffs[i]);
382  CmYawTot += sum(yawMomentCoeffs[i]);
383  }
384 
385  // Single contributions to the front and rear
386  const scalar CdfTot = 0.5*CdTot + CmRollTot;
387  const scalar CdrTot = 0.5*CdTot - CmRollTot;
388  const scalar CsfTot = 0.5*CsTot + CmYawTot;
389  const scalar CsrTot = 0.5*CsTot - CmYawTot;
390  const scalar ClfTot = 0.5*ClTot + CmPitchTot;
391  const scalar ClrTot = 0.5*ClTot - CmPitchTot;
392 
393  Log << type() << " " << name() << " execute:" << nl
394  << " Coefficients" << nl;
395 
396  writeIntegratedData("Cd", dragCoeffs);
397  writeIntegratedData("Cs", sideCoeffs);
398  writeIntegratedData("Cl", liftCoeffs);
399  writeIntegratedData("CmRoll", rollMomentCoeffs);
400  writeIntegratedData("CmPitch", pitchMomentCoeffs);
401  writeIntegratedData("CmYaw", yawMomentCoeffs);
402 
403  Log << " Cd(f) : " << CdfTot << nl
404  << " Cd(r) : " << CdrTot << nl;
405 
406  Log << " Cs(f) : " << CsfTot << nl
407  << " Cs(r) : " << CsrTot << nl;
408 
409  Log << " Cl(f) : " << ClfTot << nl
410  << " Cl(r) : " << ClrTot << nl;
411 
412  if (writeToFile())
413  {
414  writeCurrentTime(coeffFilePtr_());
415  coeffFilePtr_()
416  << tab << CdTot << tab << CsTot << tab << ClTot
417  << tab << CmRollTot << tab << CmPitchTot << tab << CmYawTot
418  << tab << CdfTot << tab << CdrTot
419  << tab << CsfTot << tab << CsrTot
420  << tab << ClfTot << tab << ClrTot << endl;
421 
422  if (nBin_ > 1)
423  {
424  if (binCumulative_)
425  {
426  forAll(liftCoeffs, i)
427  {
428  for (label bini = 1; bini < nBin_; ++bini)
429  {
430  dragCoeffs[i][bini] += dragCoeffs[i][bini-1];
431  sideCoeffs[i][bini] += sideCoeffs[i][bini-1];
432  liftCoeffs[i][bini] += liftCoeffs[i][bini-1];
433  rollMomentCoeffs[i][bini] +=
434  rollMomentCoeffs[i][bini-1];
435  pitchMomentCoeffs[i][bini] +=
436  pitchMomentCoeffs[i][bini-1];
437  yawMomentCoeffs[i][bini] += yawMomentCoeffs[i][bini-1];
438  }
439  }
440  }
441 
442  writeBinData(dragCoeffs, CdBinFilePtr_());
443  writeBinData(sideCoeffs, CsBinFilePtr_());
444  writeBinData(liftCoeffs, ClBinFilePtr_());
445  writeBinData(rollMomentCoeffs, CmRollBinFilePtr_());
446  writeBinData(pitchMomentCoeffs, CmPitchBinFilePtr_());
447  writeBinData(yawMomentCoeffs, CmYawBinFilePtr_());
448  }
449  }
450 
451  // Write state/results information
452  {
453  setResult("Cd", CdTot);
454  setResult("Cs", CsTot);
455  setResult("Cl", ClTot);
456  setResult("CmRoll", CmRollTot);
457  setResult("CmPitch", CmPitchTot);
458  setResult("CmYaw", CmYawTot);
459  setResult("Cd(f)", CdfTot);
460  setResult("Cd(r)", CdrTot);
461  setResult("Cs(f)", CsfTot);
462  setResult("Cs(r)", CsrTot);
463  setResult("Cl(f)", ClfTot);
464  setResult("Cl(r)", ClrTot);
465  }
466 
467  if (writeFields_)
468  {
469  const volVectorField& force =
470  lookupObject<volVectorField>(fieldName("force"));
471 
472  const volVectorField& moment =
473  lookupObject<volVectorField>(fieldName("moment"));
474 
475  volVectorField& forceCoeff =
476  lookupObjectRef<volVectorField>(fieldName("forceCoeff"));
477 
478  volVectorField& momentCoeff =
479  lookupObjectRef<volVectorField>(fieldName("momentCoeff"));
480 
481  dimensionedScalar f0("f0", dimForce, Aref_*pDyn);
482  dimensionedScalar m0("m0", dimForce*dimLength, Aref_*lRef_*pDyn);
483 
484  forceCoeff == force/f0;
485  momentCoeff == moment/m0;
486  }
487 
488  return true;
489 }
490 
491 
493 {
494  if (writeFields_)
495  {
496  const volVectorField& forceCoeff =
497  lookupObject<volVectorField>(fieldName("forceCoeff"));
498 
499  const volVectorField& momentCoeff =
500  lookupObject<volVectorField>(fieldName("momentCoeff"));
501 
502  forceCoeff.write();
503  momentCoeff.write();
504  }
505 
506  return true;
507 }
508 
509 
510 // ************************************************************************* //
Foam::IOobject::NO_WRITE
Definition: IOobject.H:130
volFields.H
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:104
Log
#define Log
Definition: PDRblock.C:35
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Dimensionless.
Definition: dimensionSets.H:50
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
pDyn
volScalarField pDyn(IOobject("pDyn", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE), mesh, dimensionedScalar(dimPressure, Zero))
Foam::dimLength
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:53
Foam::functionObjects::forces
Calculates the forces and moments by integrating the pressure and skin-friction forces over a given l...
Definition: forces.H:236
forceCoeffs.H
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::jn
dimensionedScalar jn(const int n, const dimensionedScalar &ds)
Definition: dimensionedScalar.C:305
Foam::read
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:108
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::writeHeader
static void writeHeader(Ostream &os, const word &fieldName)
Definition: rawSurfaceWriterImpl.C:49
Foam::dimForce
const dimensionSet dimForce
Foam::functionObjects::forceCoeffs::writeBinData
void writeBinData(const List< Field< scalar >> coeffs, Ostream &os) const
Write binned data.
Definition: forceCoeffs.C:207
Foam::functionObjects::pressure
Provides several methods to convert an input pressure field into derived forms, including:
Definition: pressure.H:349
Foam::functionObjects::forceCoeffs::read
virtual bool read(const dictionary &)
Read the forces data.
Definition: forceCoeffs.C:263
Foam::functionObjects::forceCoeffs::writeBinHeader
void writeBinHeader(const word &header, Ostream &os) const
Write header for binned data.
Definition: forceCoeffs.C:122
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::functionObjects::forces::calcForcesMoment
virtual void calcForcesMoment()
Calculate the forces and moments.
Definition: forces.C:957
Foam::dimensionedVector
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
Definition: dimensionedVector.H:50
Foam::functionObjects::forceCoeffs::writeIntegratedHeader
void writeIntegratedHeader(const word &header, Ostream &os) const
Write header for integrated data.
Definition: forceCoeffs.C:87
Foam::Field< vector >
Foam::functionObjects::forces::nBin_
label nBin_
Number of bins.
Definition: forces.H:303
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::name
word name(const complex &c)
Return string representation of complex.
Definition: complex.C:76
Foam::functionObjects::forceCoeffs::writeIntegratedData
void writeIntegratedData(const word &title, const List< Field< scalar >> &coeff) const
Write integrated data.
Definition: forceCoeffs.C:177
dragCoeffs
autoPtr< multiphaseSystem::dragCoeffFields > dragCoeffs(fluid.dragCoeffs())
IOmanip.H
Istream and Ostream manipulators taking arguments.
Foam::functionObjects::forces::read
virtual bool read(const dictionary &)
Read the forces data.
Definition: forces.C:805
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::dimensioned< scalar >
Foam::functionObjects::forceCoeffs::write
virtual bool write()
Write the forces.
Definition: forceCoeffs.C:492
Pstream.H
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::functionObjects::forceCoeffs::execute
virtual bool execute()
Execute.
Definition: forceCoeffs.C:327
Foam::functionObjects::forceCoeffs::createFiles
void createFiles()
Create the output files.
Definition: forceCoeffs.C:53
Time.H
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::tab
constexpr char tab
Definition: Ostream.H:384
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::functionObjects::writeFile::createFile
virtual autoPtr< OFstream > createFile(const word &name, scalar timeValue) const
Return autoPtr to a new file for a given time.
Definition: writeFile.C:84
Foam::functionObjects::addToRunTimeSelectionTable
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:63
Foam::token::TAB
Tab [isspace].
Definition: token.H:118
Foam::type
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:590
dictionary.H
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
Foam::functionObjects::defineTypeNameAndDebug
defineTypeNameAndDebug(ObukhovLength, 0)
Foam::functionObjects::readFields
Reads fields from the time directories and adds them to the mesh database for further post-processing...
Definition: readFields.H:155
dimensionedTypes.H
Foam::functionObjects::log
Computes the natural logarithm of an input volScalarField.
Definition: log.H:227
Foam::functionObjects::writeFile::writeToFile
virtual bool writeToFile() const
Flag to allow writing to file.
Definition: writeFile.C:254
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::List::setSize
void setSize(const label newSize)
Alias for resize(const label)
Definition: ListI.H:146
Foam::GeometricField< vector, fvPatchField, volMesh >
Foam::IOobject::NO_READ
Definition: IOobject.H:123