Go to the documentation of this file.
41 namespace functionObjects
61 if (writeToFile() && !forceFilePtr_.valid())
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];
534 lookupObjectRef<volVectorField>(fieldName(
"force"));
540 lookupObjectRef<volVectorField>(fieldName(
"moment"));
562 lookupObjectRef<volVectorField>(fieldName(
"force"));
565 lookupObjectRef<volVectorField>(fieldName(
"moment"));
569 label celli = cellIDs[i];
570 force[celli] += fN[i] + fT[i] + fP[i];
571 moment[celli] += Md[i];
578 const string& descriptor,
590 Log <<
" Sum of " << descriptor.c_str() <<
nl
591 <<
" Total : " << total <<
nl
593 <<
" Viscous : " << viscous <<
nl;
597 Log <<
" Porous : " << porous <<
nl;
604 writeCurrentTime(os);
624 writeIntegratedForceMoment
627 coordSys_.localVector(force_[0]),
628 coordSys_.localVector(force_[1]),
629 coordSys_.localVector(force_[2]),
633 writeIntegratedForceMoment
636 coordSys_.localVector(moment_[0]),
637 coordSys_.localVector(moment_[1]),
638 coordSys_.localVector(moment_[2]),
652 if ((nBin_ == 1) || !writeToFile())
661 for (
label i = 1; i <
f[0].size(); i++)
663 f[0][i] +=
f[0][i-1];
664 f[1][i] +=
f[1][i-1];
665 f[2][i] +=
f[2][i-1];
671 writeCurrentTime(os);
675 vector total =
f[0][i] +
f[1][i] +
f[2][i];
683 os <<
tab <<
f[2][i];
695 lf[0] = coordSys_.localVector(force_[0]);
696 lf[1] = coordSys_.localVector(force_[1]);
697 lf[2] = coordSys_.localVector(force_[2]);
698 lm[0] = coordSys_.localVector(moment_[0]);
699 lm[1] = coordSys_.localVector(moment_[1]);
700 lm[2] = coordSys_.localVector(moment_[2]);
702 writeBinnedForceMoment(lf, forceBinFilePtr_);
703 writeBinnedForceMoment(lm, momentBinFilePtr_);
729 directForceDensity_(
false),
741 binCumulative_(
true),
748 setCoordinateSystem(
dict);
774 directForceDensity_(
false),
786 binCumulative_(
true),
793 setCoordinateSystem(
dict);
817 initialised_ =
false;
821 directForceDensity_ =
dict.lookupOrDefault(
"directForceDensity",
false);
827 if (directForceDensity_)
830 if (
dict.readIfPresent<
word>(
"fD", fDName_))
838 if (
dict.readIfPresent<
word>(
"p", pName_))
842 if (
dict.readIfPresent<
word>(
"U", UName_))
846 if (
dict.readIfPresent<
word>(
"rho", rhoName_))
848 Info<<
" rho: " << rhoName_ <<
endl;
852 if (rhoName_ ==
"rhoInf")
854 rhoRef_ =
dict.get<scalar>(
"rhoInf");
855 Info<<
" Freestream density (rhoInf) set to " << rhoRef_ <<
endl;
859 if (
dict.readIfPresent<scalar>(
"pRef", pRef_))
861 Info<<
" Reference pressure (pRef) set to " << pRef_ <<
endl;
865 dict.readIfPresent(
"porosity", porosity_);
868 Info<<
" Including porosity effects" <<
endl;
872 Info<<
" Not including porosity effects" <<
endl;
875 if (
dict.found(
"binData"))
877 Info<<
" Activated data bins" <<
endl;
884 <<
"Number of bins (nBin) must be zero or greater"
894 Info<<
" Employing " << nBin_ <<
" bins" <<
endl;
895 if (binDict.readIfPresent(
"min", binMin_))
897 Info<<
" - min : " << binMin_ <<
endl;
899 if (binDict.readIfPresent(
"max", binMax_))
901 Info<<
" - max : " << binMax_ <<
endl;
904 binCumulative_ = binDict.get<
bool>(
"cumulative");
905 Info<<
" - cumuluative : " << binCumulative_ <<
endl;
907 binDir_ = binDict.get<
vector>(
"direction");
909 Info<<
" - direction : " << binDir_ <<
endl;
913 writeFields_ =
dict.lookupOrDefault(
"writeFields",
false);
917 Info<<
" Fields will be written" <<
endl;
936 mesh_.objectRegistry::store(forcePtr);
955 mesh_.objectRegistry::store(momentPtr);
968 if (directForceDensity_)
972 const surfaceVectorField::Boundary& Sfb = mesh_.Sf().boundaryField();
974 for (
const label patchi : patchSet_)
978 mesh_.C().boundaryField()[patchi] - coordSys_.origin()
998 addToFields(patchi, Md, fN, fT, fP);
1000 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[patchi]);
1007 const surfaceVectorField::Boundary& Sfb = mesh_.Sf().boundaryField();
1010 const volSymmTensorField::Boundary& devRhoReffb
1011 = tdevRhoReff().boundaryField();
1014 scalar pRef = pRef_/
rho(
p);
1016 for (
const label patchi : patchSet_)
1020 mesh_.C().boundaryField()[patchi] - coordSys_.origin()
1025 rho(
p)*Sfb[patchi]*(
p.boundaryField()[patchi] - pRef)
1028 vectorField fT(Sfb[patchi] & devRhoReffb[patchi]);
1032 addToFields(patchi, Md, fN, fT, fP);
1034 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[patchi]);
1050 <<
"Porosity effects requested, but no porosity models found "
1051 <<
"in the database"
1064 for (
const label zonei : cellZoneIDs)
1066 const cellZone& cZone = mesh_.cellZones()[zonei];
1074 addToFields(cZone, Md, fDummy, fDummy, fP);
1076 applyBins(Md, fDummy, fDummy, fP, d);
1090 return sum(force_[0]) +
sum(force_[1]) +
sum(force_[2]);
1096 return sum(moment_[0]) +
sum(moment_[1]) +
sum(moment_[2]);
1116 setResult(
"normalForce",
sum(force_[0]));
1117 setResult(
"tangentialForce",
sum(force_[1]));
1118 setResult(
"porousForce",
sum(force_[2]));
1120 setResult(
"normalMoment",
sum(moment_[0]));
1121 setResult(
"tangentialMoment",
sum(moment_[1]));
1122 setResult(
"porousMoment",
sum(moment_[2]));
1132 lookupObject<volVectorField>(fieldName(
"force")).write();
1133 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.
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...
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.
Includes tools to manipulate the pressure into different forms.
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.
addToRunTimeSelectionTable(functionObject, add, dictionary)
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.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
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.
static bool master(const label communicator=0)
Am I the master process.
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)
defineTypeNameAndDebug(fvMeshFunctionObject, 0)
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.
A Cartesian coordinate system.
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
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.
labelHashSet patchSet(const UList< wordRe > &patchNames, const bool warnNotFound=true, const bool useGroups=true) const
Return the set of patch IDs corresponding to the given names.
static tmp< T > New(Args &&... args)
Construct tmp of T with forwarding arguments.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
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< scalar > zero
functionObject base class for writing single files
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.
#define Log
Report write to Foam::Info if the local log switch is true.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
dimensionedSymmTensor dev(const dimensionedSymmTensor &dt)