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  const auto& coordSys = coordSysPtr_();
93  writeHeader(os, "Force coefficients");
94  writeHeaderValue(os, "dragDir", coordSys.e1());
95  writeHeaderValue(os, "sideDir", coordSys.e2());
96  writeHeaderValue(os, "liftDir", coordSys.e3());
97  writeHeaderValue(os, "rollAxis", coordSys.e1());
98  writeHeaderValue(os, "pitchAxis", coordSys.e2());
99  writeHeaderValue(os, "yawAxis", coordSys.e3());
100  writeHeaderValue(os, "magUInf", magUInf_);
101  writeHeaderValue(os, "lRef", lRef_);
102  writeHeaderValue(os, "Aref", Aref_);
103  writeHeaderValue(os, "CofR", coordSys.origin());
104  writeHeader(os, "");
105  writeCommented(os, "Time");
106  writeTabbed(os, "Cd");
107  writeTabbed(os, "Cs");
108  writeTabbed(os, "Cl");
109  writeTabbed(os, "CmRoll");
110  writeTabbed(os, "CmPitch");
111  writeTabbed(os, "CmYaw");
112  writeTabbed(os, "Cd(f)");
113  writeTabbed(os, "Cd(r)");
114  writeTabbed(os, "Cs(f)");
115  writeTabbed(os, "Cs(r)");
116  writeTabbed(os, "Cl(f)");
117  writeTabbed(os, "Cl(r)");
118  os << endl;
119 }
120 
121 
123 (
124  const word& header,
125  Ostream& os
126 ) const
127 {
128  writeHeader(os, header);
129  writeHeaderValue(os, "bins", nBin_);
130  writeHeaderValue(os, "start", binMin_);
131  writeHeaderValue(os, "delta", binDx_);
132  writeHeaderValue(os, "direction", binDir_);
133 
134  vectorField binPoints(nBin_);
135  writeCommented(os, "x co-ords :");
136  forAll(binPoints, pointi)
137  {
138  binPoints[pointi] = (binMin_ + (pointi + 1)*binDx_)*binDir_;
139  os << tab << binPoints[pointi].x();
140  }
141  os << nl;
142 
143  writeCommented(os, "y co-ords :");
144  forAll(binPoints, pointi)
145  {
146  os << tab << binPoints[pointi].y();
147  }
148  os << nl;
149 
150  writeCommented(os, "z co-ords :");
151  forAll(binPoints, pointi)
152  {
153  os << tab << binPoints[pointi].z();
154  }
155  os << nl;
156 
157  writeHeader(os, "");
158  writeCommented(os, "Time");
159 
160  for (label j = 0; j < nBin_; ++j)
161  {
162  const word jn(Foam::name(j) + ':');
163  writeTabbed(os, jn + "total");
164  writeTabbed(os, jn + "pressure");
165  writeTabbed(os, jn + "viscous");
166 
167  if (porosity_)
168  {
169  writeTabbed(os, jn + "porous");
170  }
171  }
172 
173  os << endl;
174 }
175 
176 
178 (
179  const word& title,
180  const List<Field<scalar>>& coeff
181 ) const
182 {
183  if (!log)
184  {
185  return;
186  }
187 
188  const scalar pressure = sum(coeff[0]);
189  const scalar viscous = sum(coeff[1]);
190  const scalar porous = sum(coeff[2]);
191  const scalar total = pressure + viscous + porous;
192 
193  Info<< " " << title << " : " << total << token::TAB
194  << '('
195  << "pressure: " << pressure << token::TAB
196  << "viscous: " << viscous;
197 
198  if (porosity_)
199  {
200  Info<< token::TAB << "porous: " << porous;
201  }
202 
203  Info<< ')' << endl;
204 }
205 
206 
208 (
209  const List<Field<scalar>> coeffs,
210  Ostream& os
211 ) const
212 {
213  writeCurrentTime(os);
214 
215  for (label bini = 0; bini < nBin_; ++bini)
216  {
217  scalar total = coeffs[0][bini] + coeffs[1][bini] + coeffs[2][bini];
218 
219  os << tab << total << tab << coeffs[0][bini] << tab << coeffs[1][bini];
220 
221  if (porosity_)
222  {
223  os << tab << coeffs[2][bini];
224  }
225  }
226 
227  os << endl;
228 }
229 
230 
231 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
232 
233 Foam::functionObjects::forceCoeffs::forceCoeffs
234 (
235  const word& name,
236  const Time& runTime,
237  const dictionary& dict,
238  const bool readFields
239 )
240 :
241  forces(name, runTime, dict, false),
242  magUInf_(Zero),
243  lRef_(Zero),
244  Aref_(Zero),
245  coeffFilePtr_(),
246  CdBinFilePtr_(),
247  CsBinFilePtr_(),
248  ClBinFilePtr_(),
249  CmRollBinFilePtr_(),
250  CmPitchBinFilePtr_(),
251  CmYawBinFilePtr_()
252 {
253  if (readFields)
254  {
255  read(dict);
256  setCoordinateSystem(dict, "liftDir", "dragDir");
257  Info<< endl;
258  }
259 }
260 
261 
262 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
263 
265 {
267 
268  // Free stream velocity magnitude
269  dict.readEntry("magUInf", magUInf_);
270 
271  // If case is compressible we must read rhoInf (store in rhoRef_) to
272  // calculate the reference dynamic pressure
273  // Note: for incompressible, rhoRef_ is already initialised
274  if (rhoName_ != "rhoInf")
275  {
276  dict.readEntry("rhoInf", rhoRef_);
277  }
278 
279  // Reference length and area scales
280  dict.readEntry("lRef", lRef_);
281  dict.readEntry("Aref", Aref_);
282 
283  if (writeFields_)
284  {
285  volVectorField* forceCoeffPtr
286  (
287  new volVectorField
288  (
289  IOobject
290  (
291  scopedName("forceCoeff"),
292  mesh_.time().timeName(),
293  mesh_,
296  ),
297  mesh_,
299  )
300  );
301 
302  mesh_.objectRegistry::store(forceCoeffPtr);
303 
304  volVectorField* momentCoeffPtr
305  (
306  new volVectorField
307  (
308  IOobject
309  (
310  scopedName("momentCoeff"),
311  mesh_.time().timeName(),
312  mesh_,
315  ),
316  mesh_,
318  )
319  );
320 
321  mesh_.objectRegistry::store(momentCoeffPtr);
322  }
323 
324  return true;
325 }
326 
327 
329 {
331 
332  createFiles();
333 
334  // Storage for pressure, viscous and porous contributions to coeffs
336  List<Field<scalar>> sideCoeffs(3);
337  List<Field<scalar>> liftCoeffs(3);
338  List<Field<scalar>> rollMomentCoeffs(3);
339  List<Field<scalar>> pitchMomentCoeffs(3);
340  List<Field<scalar>> yawMomentCoeffs(3);
341 
342  forAll(liftCoeffs, i)
343  {
344  dragCoeffs[i].setSize(nBin_);
345  sideCoeffs[i].setSize(nBin_);
346  liftCoeffs[i].setSize(nBin_);
347  rollMomentCoeffs[i].setSize(nBin_);
348  pitchMomentCoeffs[i].setSize(nBin_);
349  yawMomentCoeffs[i].setSize(nBin_);
350  }
351 
352  // Calculate coefficients
353  scalar CdTot = 0;
354  scalar CsTot = 0;
355  scalar ClTot = 0;
356  scalar CmRollTot = 0;
357  scalar CmPitchTot = 0;
358  scalar CmYawTot = 0;
359 
360  const scalar pDyn = 0.5*rhoRef_*sqr(magUInf_);
361 
362  // Avoid divide by zero in 2D cases
363  const scalar momentScaling = 1.0/(Aref_*pDyn*lRef_ + SMALL);
364  const scalar forceScaling = 1.0/(Aref_*pDyn + SMALL);
365 
366  const auto& coordSys = coordSysPtr_();
367 
368  forAll(liftCoeffs, i)
369  {
370  const Field<vector> localForce(coordSys.localVector(force_[i]));
371  const Field<vector> localMoment(coordSys.localVector(moment_[i]));
372 
373  dragCoeffs[i] = forceScaling*(localForce.component(0));
374  sideCoeffs[i] = forceScaling*(localForce.component(1));
375  liftCoeffs[i] = forceScaling*(localForce.component(2));
376  rollMomentCoeffs[i] = momentScaling*(localMoment.component(0));
377  pitchMomentCoeffs[i] = momentScaling*(localMoment.component(1));
378  yawMomentCoeffs[i] = momentScaling*(localMoment.component(2));
379 
380  CdTot += sum(dragCoeffs[i]);
381  CsTot += sum(sideCoeffs[i]);
382  ClTot += sum(liftCoeffs[i]);
383  CmRollTot += sum(rollMomentCoeffs[i]);
384  CmPitchTot += sum(pitchMomentCoeffs[i]);
385  CmYawTot += sum(yawMomentCoeffs[i]);
386  }
387 
388  // Single contributions to the front and rear
389  const scalar CdfTot = 0.5*CdTot + CmRollTot;
390  const scalar CdrTot = 0.5*CdTot - CmRollTot;
391  const scalar CsfTot = 0.5*CsTot + CmYawTot;
392  const scalar CsrTot = 0.5*CsTot - CmYawTot;
393  const scalar ClfTot = 0.5*ClTot + CmPitchTot;
394  const scalar ClrTot = 0.5*ClTot - CmPitchTot;
395 
396  Log << type() << " " << name() << " execute:" << nl
397  << " Coefficients" << nl;
398 
399  writeIntegratedData("Cd", dragCoeffs);
400  writeIntegratedData("Cs", sideCoeffs);
401  writeIntegratedData("Cl", liftCoeffs);
402  writeIntegratedData("CmRoll", rollMomentCoeffs);
403  writeIntegratedData("CmPitch", pitchMomentCoeffs);
404  writeIntegratedData("CmYaw", yawMomentCoeffs);
405 
406  Log << " Cd(f) : " << CdfTot << nl
407  << " Cd(r) : " << CdrTot << nl;
408 
409  Log << " Cs(f) : " << CsfTot << nl
410  << " Cs(r) : " << CsrTot << nl;
411 
412  Log << " Cl(f) : " << ClfTot << nl
413  << " Cl(r) : " << ClrTot << nl;
414 
415  if (writeToFile())
416  {
417  writeCurrentTime(coeffFilePtr_());
418  coeffFilePtr_()
419  << tab << CdTot << tab << CsTot << tab << ClTot
420  << tab << CmRollTot << tab << CmPitchTot << tab << CmYawTot
421  << tab << CdfTot << tab << CdrTot
422  << tab << CsfTot << tab << CsrTot
423  << tab << ClfTot << tab << ClrTot << endl;
424 
425  if (nBin_ > 1)
426  {
427  if (binCumulative_)
428  {
429  forAll(liftCoeffs, i)
430  {
431  for (label bini = 1; bini < nBin_; ++bini)
432  {
433  dragCoeffs[i][bini] += dragCoeffs[i][bini-1];
434  sideCoeffs[i][bini] += sideCoeffs[i][bini-1];
435  liftCoeffs[i][bini] += liftCoeffs[i][bini-1];
436  rollMomentCoeffs[i][bini] +=
437  rollMomentCoeffs[i][bini-1];
438  pitchMomentCoeffs[i][bini] +=
439  pitchMomentCoeffs[i][bini-1];
440  yawMomentCoeffs[i][bini] += yawMomentCoeffs[i][bini-1];
441  }
442  }
443  }
444 
445  writeBinData(dragCoeffs, CdBinFilePtr_());
446  writeBinData(sideCoeffs, CsBinFilePtr_());
447  writeBinData(liftCoeffs, ClBinFilePtr_());
448  writeBinData(rollMomentCoeffs, CmRollBinFilePtr_());
449  writeBinData(pitchMomentCoeffs, CmPitchBinFilePtr_());
450  writeBinData(yawMomentCoeffs, CmYawBinFilePtr_());
451  }
452  }
453 
454  // Write state/results information
455  {
456  setResult("Cd", CdTot);
457  setResult("Cs", CsTot);
458  setResult("Cl", ClTot);
459  setResult("CmRoll", CmRollTot);
460  setResult("CmPitch", CmPitchTot);
461  setResult("CmYaw", CmYawTot);
462  setResult("Cd(f)", CdfTot);
463  setResult("Cd(r)", CdrTot);
464  setResult("Cs(f)", CsfTot);
465  setResult("Cs(r)", CsrTot);
466  setResult("Cl(f)", ClfTot);
467  setResult("Cl(r)", ClrTot);
468  }
469 
470  if (writeFields_)
471  {
472  const volVectorField& force =
473  lookupObject<volVectorField>(scopedName("force"));
474 
475  const volVectorField& moment =
476  lookupObject<volVectorField>(scopedName("moment"));
477 
478  volVectorField& forceCoeff =
479  lookupObjectRef<volVectorField>(scopedName("forceCoeff"));
480 
481  volVectorField& momentCoeff =
482  lookupObjectRef<volVectorField>(scopedName("momentCoeff"));
483 
484  dimensionedScalar f0("f0", dimForce, Aref_*pDyn);
485  dimensionedScalar m0("m0", dimForce*dimLength, Aref_*lRef_*pDyn);
486 
487  forceCoeff == force/f0;
488  momentCoeff == moment/m0;
489  }
490 
491  return true;
492 }
493 
494 
496 {
497  if (writeFields_)
498  {
499  const volVectorField& forceCoeff =
500  lookupObject<volVectorField>(scopedName("forceCoeff"));
501 
502  const volVectorField& momentCoeff =
503  lookupObject<volVectorField>(scopedName("momentCoeff"));
504 
505  forceCoeff.write();
506  momentCoeff.write();
507  }
508 
509  return true;
510 }
511 
512 
513 // ************************************************************************* //
Foam::IOobject::NO_WRITE
Definition: IOobject.H:195
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:169
Log
#define Log
Definition: PDRblock.C:35
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:65
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:52
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:369
Foam::writeHeader
static void writeHeader(Ostream &os, const word &fieldName)
Definition: rawSurfaceWriterImpl.C:66
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:208
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:264
Foam::functionObjects::forceCoeffs::writeBinHeader
void writeBinHeader(const word &header, Ostream &os) const
Write header for binned data.
Definition: forceCoeffs.C:123
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:951
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 (stdout output on master, null elsewhere)
Foam::functionObjects::forceCoeffs::writeIntegratedData
void writeIntegratedData(const word &title, const List< Field< scalar >> &coeff) const
Write integrated data.
Definition: forceCoeffs.C:178
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
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:799
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:123
os
OBJstream os(runTime.globalPath()/outputName)
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:495
Pstream.H
fvMesh.H
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::functionObjects::forceCoeffs::execute
virtual bool execute()
Execute.
Definition: forceCoeffs.C:328
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:403
Foam::nl
constexpr char nl
Definition: Ostream.H:404
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:83
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:123
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::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
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:253
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::GeometricField< vector, fvPatchField, volMesh >
Foam::IOobject::NO_READ
Definition: IOobject.H:188
Foam::dimless
const dimensionSet dimless
Dimensionless.
Definition: dimensionSets.C:189