Go to the documentation of this file.
41 namespace functionObjects
61 if (writeToFile() && !forceFilePtr_)
63 forceFilePtr_ = createFile(
"force");
64 writeIntegratedHeader(
"Force", forceFilePtr_());
65 momentFilePtr_ = createFile(
"moment");
66 writeIntegratedHeader(
"Moment", momentFilePtr_());
70 forceBinFilePtr_ = createFile(
"forceBin");
71 writeBinHeader(
"Force", forceBinFilePtr_());
72 momentBinFilePtr_ = createFile(
"momentBin");
73 writeBinHeader(
"Moment", momentBinFilePtr_());
86 writeHeaderValue(os,
"CofR", coordSys_.origin());
88 writeCommented(os,
"Time");
89 writeTabbed(os,
"(total_x total_y total_z)");
90 writeTabbed(os,
"(pressure_x pressure_y pressure_z)");
91 writeTabbed(os,
"(viscous_x viscous_y viscous_z)");
95 writeTabbed(os,
"(porous_x porous_y porous_z)");
109 writeHeaderValue(os,
"bins", nBin_);
110 writeHeaderValue(os,
"start", binMin_);
111 writeHeaderValue(os,
"end", binMax_);
112 writeHeaderValue(os,
"delta", binDx_);
113 writeHeaderValue(os,
"direction", binDir_);
116 writeCommented(os,
"x co-ords :");
119 binPoints[pointi] = (binMin_ + (pointi + 1)*binDx_)*binDir_;
120 os <<
tab << binPoints[pointi].x();
124 writeCommented(os,
"y co-ords :");
127 os <<
tab << binPoints[pointi].y();
131 writeCommented(os,
"z co-ords :");
134 os <<
tab << binPoints[pointi].z();
139 writeCommented(os,
"Time");
141 for (label j = 0; j < nBin_; j++)
144 os <<
tab <<
jn <<
"(total_x total_y total_z)"
145 <<
tab <<
jn <<
"(pressure_x pressure_y pressure_z)"
146 <<
tab <<
jn <<
"(viscous_x viscous_y viscous_z)";
150 os <<
tab <<
jn <<
"(porous_x porous_y porous_z)";
167 if (
dict.readIfPresent<
point>(
"CofR", coordSys_.origin()))
182 if (
dict.found(coordinateSystem::typeName_()))
190 coordinateSystem::typeName_()
209 if (directForceDensity_)
211 if (!foundObject<volVectorField>(fDName_))
214 <<
"Could not find " << fDName_ <<
" in database"
222 !foundObject<volVectorField>(UName_)
223 || !foundObject<volScalarField>(pName_)
228 <<
"Could not find U: " << UName_ <<
" or p:" << pName_
233 if (rhoName_ !=
"rhoInf" && !foundObject<volScalarField>(rhoName_))
236 <<
"Could not find rho:" << rhoName_
254 scalar geomMin = GREAT;
255 scalar geomMax = -GREAT;
256 for (
const label patchi : patchSet_)
260 geomMin =
min(
min(d), geomMin);
261 geomMax =
max(
max(d), geomMax);
277 for (
const label zonei : cellZoneIDs)
279 const cellZone& cZone = mesh_.cellZones()[zonei];
281 geomMin =
min(
min(d), geomMin);
282 geomMax =
max(
max(d), geomMax);
291 geomMax = 1.0001*(geomMax - geomMin) + geomMin;
294 if (binMin_ == GREAT)
298 if (binMax_ == GREAT)
303 binDx_ = (binMax_ - binMin_)/scalar(nBin_);
306 binPoints_.setSize(nBin_);
309 binPoints_[i] = (i + 0.5)*binDir_*binDx_;
335 lookupObjectRef<volVectorField>(fieldName(
"force"));
340 lookupObjectRef<volVectorField>(fieldName(
"moment"));
353 if (foundObject<cmpTurbModel>(cmpTurbModel::propertiesName))
355 const cmpTurbModel&
turb =
356 lookupObject<cmpTurbModel>(cmpTurbModel::propertiesName);
358 return turb.devRhoReff();
360 else if (foundObject<icoTurbModel>(icoTurbModel::propertiesName))
363 lookupObject<icoTurbModel>(icoTurbModel::propertiesName);
376 else if (foundObject<transportModel>(
"transportProperties"))
379 lookupObject<transportModel>(
"transportProperties");
385 else if (foundObject<dictionary>(
"transportProperties"))
388 lookupObject<dictionary>(
"transportProperties");
399 <<
"No valid model for viscous stress calculation"
416 else if (foundObject<transportModel>(
"transportProperties"))
419 lookupObject<transportModel>(
"transportProperties");
421 return rho()*laminarT.
nu();
423 else if (foundObject<dictionary>(
"transportProperties"))
426 lookupObject<dictionary>(
"transportProperties");
435 <<
"No valid model for dynamic viscosity calculation"
445 if (rhoName_ ==
"rhoInf")
452 mesh_.time().timeName(),
460 return(lookupObject<volScalarField>(rhoName_));
471 if (rhoName_ !=
"rhoInf")
474 <<
"Dynamic pressure is expected but kinematic is provided."
493 force_[0][0] +=
sum(fN);
494 force_[1][0] +=
sum(fT);
495 force_[2][0] +=
sum(fP);
496 moment_[0][0] +=
sum(Md^fN);
497 moment_[1][0] +=
sum(Md^fT);
498 moment_[2][0] +=
sum(Md^fP);
506 label bini =
min(
max(floor(dd[i]/binDx_), 0), force_[0].size() - 1);
508 force_[0][bini] += fN[i];
509 force_[1][bini] += fT[i];
510 force_[2][bini] += fP[i];
511 moment_[0][bini] += Md[i]^fN[i];
512 moment_[1][bini] += Md[i]^fT[i];
513 moment_[2][bini] += Md[i]^fP[i];
533 auto& force = lookupObjectRef<volVectorField>(fieldName(
"force"));
534 vectorField& pf = force.boundaryFieldRef()[patchi];
537 auto& moment = lookupObjectRef<volVectorField>(fieldName(
"moment"));
538 vectorField& pm = moment.boundaryFieldRef()[patchi];
557 auto& force = lookupObjectRef<volVectorField>(fieldName(
"force"));
558 auto& moment = lookupObjectRef<volVectorField>(fieldName(
"moment"));
562 label celli = cellIDs[i];
563 force[celli] += fN[i] + fT[i] + fP[i];
564 moment[celli] = Md[i]^force[celli];
571 const string& descriptor,
583 Log <<
" Sum of " << descriptor.c_str() <<
nl
584 <<
" Total : " << total <<
nl
586 <<
" Viscous : " << viscous <<
nl;
590 Log <<
" Porous : " << porous <<
nl;
597 writeCurrentTime(os);
617 writeIntegratedForceMoment
620 coordSys_.localVector(force_[0]),
621 coordSys_.localVector(force_[1]),
622 coordSys_.localVector(force_[2]),
626 writeIntegratedForceMoment
629 coordSys_.localVector(moment_[0]),
630 coordSys_.localVector(moment_[1]),
631 coordSys_.localVector(moment_[2]),
645 if ((nBin_ == 1) || !writeToFile())
654 for (label i = 1; i <
f[0].size(); i++)
656 f[0][i] +=
f[0][i-1];
657 f[1][i] +=
f[1][i-1];
658 f[2][i] +=
f[2][i-1];
664 writeCurrentTime(os);
668 vector total =
f[0][i] +
f[1][i] +
f[2][i];
676 os <<
tab <<
f[2][i];
688 lf[0] = coordSys_.localVector(force_[0]);
689 lf[1] = coordSys_.localVector(force_[1]);
690 lf[2] = coordSys_.localVector(force_[2]);
691 lm[0] = coordSys_.localVector(moment_[0]);
692 lm[1] = coordSys_.localVector(moment_[1]);
693 lm[2] = coordSys_.localVector(moment_[2]);
695 writeBinnedForceMoment(lf, forceBinFilePtr_);
696 writeBinnedForceMoment(lm, momentBinFilePtr_);
722 directForceDensity_(
false),
734 binCumulative_(
true),
741 setCoordinateSystem(
dict);
767 directForceDensity_(
false),
779 binCumulative_(
true),
786 setCoordinateSystem(
dict);
810 initialised_ =
false;
814 directForceDensity_ =
dict.getOrDefault(
"directForceDensity",
false);
817 mesh_.boundaryMesh().patchSet
822 if (directForceDensity_)
825 if (
dict.readIfPresent<
word>(
"fD", fDName_))
833 if (
dict.readIfPresent<
word>(
"p", pName_))
837 if (
dict.readIfPresent<
word>(
"U", UName_))
841 if (
dict.readIfPresent<
word>(
"rho", rhoName_))
843 Info<<
" rho: " << rhoName_ <<
endl;
847 if (rhoName_ ==
"rhoInf")
849 rhoRef_ =
dict.get<scalar>(
"rhoInf");
850 Info<<
" Freestream density (rhoInf) set to " << rhoRef_ <<
endl;
854 if (
dict.readIfPresent<scalar>(
"pRef", pRef_))
856 Info<<
" Reference pressure (pRef) set to " << pRef_ <<
endl;
860 dict.readIfPresent(
"porosity", porosity_);
863 Info<<
" Including porosity effects" <<
endl;
867 Info<<
" Not including porosity effects" <<
endl;
870 if (
dict.found(
"binData"))
872 Info<<
" Activated data bins" <<
endl;
874 nBin_ = binDict.
get<label>(
"nBin");
879 <<
"Number of bins (nBin) must be zero or greater"
889 Info<<
" Employing " << nBin_ <<
" bins" <<
endl;
890 if (binDict.readIfPresent(
"min", binMin_))
892 Info<<
" - min : " << binMin_ <<
endl;
894 if (binDict.readIfPresent(
"max", binMax_))
896 Info<<
" - max : " << binMax_ <<
endl;
899 binCumulative_ = binDict.get<
bool>(
"cumulative");
900 Info<<
" - cumuluative : " << binCumulative_ <<
endl;
902 binDir_ = binDict.get<
vector>(
"direction");
904 Info<<
" - direction : " << binDir_ <<
endl;
908 writeFields_ =
dict.getOrDefault(
"writeFields",
false);
912 Info<<
" Fields will be written" <<
endl;
931 mesh_.objectRegistry::store(forcePtr);
950 mesh_.objectRegistry::store(momentPtr);
963 if (directForceDensity_)
967 const surfaceVectorField::Boundary& Sfb = mesh_.Sf().boundaryField();
969 for (
const label patchi : patchSet_)
973 mesh_.C().boundaryField()[patchi] - coordSys_.origin()
993 addToFields(patchi, Md, fN, fT, fP);
995 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[patchi]);
1002 const surfaceVectorField::Boundary& Sfb = mesh_.Sf().boundaryField();
1005 const volSymmTensorField::Boundary& devRhoReffb
1006 = tdevRhoReff().boundaryField();
1009 scalar pRef = pRef_/
rho(
p);
1011 for (
const label patchi : patchSet_)
1015 mesh_.C().boundaryField()[patchi] - coordSys_.origin()
1020 rho(
p)*Sfb[patchi]*(
p.boundaryField()[patchi] - pRef)
1023 vectorField fT(Sfb[patchi] & devRhoReffb[patchi]);
1027 addToFields(patchi, Md, fN, fT, fP);
1029 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[patchi]);
1045 <<
"Porosity effects requested, but no porosity models found "
1046 <<
"in the database"
1059 for (
const label zonei : cellZoneIDs)
1061 const cellZone& cZone = mesh_.cellZones()[zonei];
1069 addToFields(cZone, Md, fDummy, fDummy, fP);
1071 applyBins(Md, fDummy, fDummy, fP, d);
1085 return sum(force_[0]) +
sum(force_[1]) +
sum(force_[2]);
1091 return sum(moment_[0]) +
sum(moment_[1]) +
sum(moment_[2]);
1111 setResult(
"normalForce",
sum(force_[0]));
1112 setResult(
"tangentialForce",
sum(force_[1]));
1113 setResult(
"porousForce",
sum(force_[2]));
1115 setResult(
"normalMoment",
sum(moment_[0]));
1116 setResult(
"tangentialMoment",
sum(moment_[1]));
1117 setResult(
"porousMoment",
sum(moment_[2]));
1127 lookupObject<volVectorField>(fieldName(
"force")).write();
1128 lookupObject<volVectorField>(fieldName(
"moment")).write();
virtual vector forceEff() const
Return the total force.
const dimensionSet dimPressure
Defines the attributes of an object for which implicit objectRegistry management is supported,...
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
tmp< volScalarField > mu() const
Dynamic viscosity field.
A class for handling words, derived from Foam::string.
const labelList & cellZoneIDs() const
Return const access to the cell zone IDs.
void writeForces()
Write force data.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
virtual tmp< volScalarField > nu() const =0
Return the laminar viscosity.
const dimensionedScalar mu
Atomic mass unit.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
A class for managing temporary objects.
static constexpr const zero Zero
Global zero (0)
const dimensionSet dimDensity
virtual bool write()
Write the forces.
dimensionedScalar jn(const int n, const dimensionedScalar &ds)
bool read(const char *buf, int32_t &val)
Same as readInt32.
IOdictionary transportProperties(IOobject("transportProperties", runTime.constant(), mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
void writeBinHeader(const word &header, Ostream &os) const
Write header for binned data.
word fieldName(const word &name) const
Create a field name.
Fundamental fluid thermodynamic properties.
Basic thermodynamics type based on the use of fitting functions for cp, h, s obtained from the templa...
static bool master(const label communicator=worldComm)
Am I the master process.
Ostream & endl(Ostream &os)
Add newline and flush stream.
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
static void writeHeader(Ostream &os, const word &fieldName)
void writeIntegratedForceMoment(const string &descriptor, const vectorField &fm0, const vectorField &fm1, const vectorField &fm2, autoPtr< OFstream > &osPtr) const
Helper function to write integrated forces and moments.
void writeBins()
Write binned data.
const dimensionSet dimForce
Vector< Cmpt > & normalise()
Normalise the vector by its magnitude.
Provides several methods to convert an input pressure field into derived forms, including:
Specialization of Foam::functionObject for an Foam::fvMesh, providing a reference to the Foam::fvMesh...
void setCoordinateSystem(const dictionary &dict, const word &e3Name=word::null, const word &e1Name=word::null)
Set the co-ordinate system from dictionary and axes names.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
#define forAll(list, i)
Loop across all elements in list.
virtual void calcForcesMoment()
Calculate the forces and moments.
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
void initialiseBins()
Initialise the collection bins.
Registry of regIOobjects.
tmp< volScalarField > rho() const
Return rho if specified otherwise rhoRef.
virtual bool read(const dictionary &dict)
Read.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
virtual tmp< vectorField > force(const volVectorField &U, const volScalarField &rho, const volScalarField &mu)
Return the force over the cell zone(s)
virtual vector momentEff() const
Return the total moment.
void resetFields()
Reset the fields prior to accumulation of force/moments.
void initialise()
Initialise the fields.
messageStream Info
Information stream (uses stdout - output is on the master only)
A patch is a list of labels that address the faces in the global face list.
word name(const complex &c)
Return string representation of complex.
tmp< volSymmTensorField > devRhoReff() const
Return the effective viscous stress (laminar + turbulent).
static autoPtr< coordinateSystem > New(word modelType, const objectRegistry &obr, const dictionary &dict)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
virtual bool read(const dictionary &)
Read the forces data.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
word dictName() const
The local dictionary name (final part of scoped name)
const dimensionSet dimViscosity
void addToFields(const label patchi, const vectorField &Md, const vectorField &fN, const vectorField &fT, const vectorField &fP)
Add patch contributions to force and moment fields.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
virtual bool execute()
Execute, currently does nothing.
virtual bool read(const dictionary &dict)
Read optional controls.
Macros for easy insertion into run-time selection tables.
void writeIntegratedHeader(const word &header, Ostream &os) const
Write header for integrated data.
Vector< scalar > vector
A scalar version of the templated Vector.
void writeBinnedForceMoment(const List< Field< vector >> &fm, autoPtr< OFstream > &osPtr) const
Helper function to write binned forces and moments.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Base-class for all transport models used by the incompressible turbulence models.
A HashTable similar to std::unordered_map.
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Top level model for porosity models.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
void applyBins(const vectorField &Md, const vectorField &fN, const vectorField &fT, const vectorField &fP, const vectorField &d)
Accumulate bin data.
forAllConstIters(mixture.phases(), phase)
const vectorField::subField faceCentres() const
Return face centres.
const word & name() const
Return the name of this functionObject.
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
A Cartesian coordinate system.
Templated wrapper class to provide compressible turbulence models thermal diffusivity based thermal t...
void createFiles()
Create the output files.
Calculate the gradient of the given field.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
A List of wordRe with additional matching capabilities.
static tmp< T > New(Args &&... args)
Construct tmp of T with forwarding arguments.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
defineTypeNameAndDebug(ObukhovLength, 0)
static const word null
An empty word.
Reads fields from the time directories and adds them to the mesh database for further post-processing...
static const Vector< Cmpt > zero
Base class for writing single files from the function objects.
Templated abstract base class for single-phase incompressible turbulence models.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
bool empty() const noexcept
True if the hash table is empty.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
static const GeometricField< symmTensor, fvPatchField, volMesh > & null()
Return a null geometric field.
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
compressible::turbulenceModel & turb
#define WarningInFunction
Report a warning using Foam::Warning.
dimensionedSymmTensor twoSymm(const dimensionedSymmTensor &dt)
forces(const forces &)=delete
No copy construct.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
dimensionedSymmTensor dev(const dimensionedSymmTensor &dt)