Go to the documentation of this file.
41 namespace functionObjects
80 writeHeaderValue(
os,
"CofR", coordSysPtr_->origin());
82 writeCommented(
os,
"Time");
83 writeTabbed(
os,
"(total_x total_y total_z)");
84 writeTabbed(
os,
"(pressure_x pressure_y pressure_z)");
85 writeTabbed(
os,
"(viscous_x viscous_y viscous_z)");
89 writeTabbed(
os,
"(porous_x porous_y porous_z)");
103 writeHeaderValue(
os,
"bins", nBin_);
104 writeHeaderValue(
os,
"start", binMin_);
105 writeHeaderValue(
os,
"end", binMax_);
106 writeHeaderValue(
os,
"delta", binDx_);
107 writeHeaderValue(
os,
"direction", binDir_);
110 writeCommented(
os,
"x co-ords :");
113 binPoints[pointi] = (binMin_ + (pointi + 1)*binDx_)*binDir_;
114 os <<
tab << binPoints[pointi].x();
118 writeCommented(
os,
"y co-ords :");
121 os <<
tab << binPoints[pointi].y();
125 writeCommented(
os,
"z co-ords :");
128 os <<
tab << binPoints[pointi].z();
133 writeCommented(
os,
"Time");
135 for (label j = 0; j < nBin_; j++)
138 os <<
tab <<
jn <<
"(total_x total_y total_z)"
139 <<
tab <<
jn <<
"(pressure_x pressure_y pressure_z)"
140 <<
tab <<
jn <<
"(viscous_x viscous_y viscous_z)";
144 os <<
tab <<
jn <<
"(porous_x porous_y porous_z)";
159 coordSysPtr_.clear();
162 if (
dict.readIfPresent<
point>(
"CofR", origin))
176 if (
dict.found(coordinateSystem::typeName_()))
184 coordinateSystem::typeName_()
203 if (directForceDensity_)
205 if (!foundObject<volVectorField>(fDName_))
208 <<
"Could not find " << fDName_ <<
" in database"
216 !foundObject<volVectorField>(UName_)
217 || !foundObject<volScalarField>(pName_)
222 <<
"Could not find U: " << UName_ <<
" or p:" << pName_
227 if (rhoName_ !=
"rhoInf" && !foundObject<volScalarField>(rhoName_))
230 <<
"Could not find rho:" << rhoName_
248 scalar geomMin = GREAT;
249 scalar geomMax = -GREAT;
250 for (
const label patchi : patchSet_)
254 geomMin =
min(
min(d), geomMin);
255 geomMax =
max(
max(d), geomMax);
271 for (
const label zonei : cellZoneIDs)
273 const cellZone& cZone = mesh_.cellZones()[zonei];
275 geomMin =
min(
min(d), geomMin);
276 geomMax =
max(
max(d), geomMax);
285 geomMax = 1.0001*(geomMax - geomMin) + geomMin;
288 if (binMin_ == GREAT)
292 if (binMax_ == GREAT)
297 binDx_ = (binMax_ - binMin_)/scalar(nBin_);
300 binPoints_.setSize(nBin_);
303 binPoints_[i] = (i + 0.5)*binDir_*binDx_;
329 lookupObjectRef<volVectorField>(scopedName(
"force"));
334 lookupObjectRef<volVectorField>(scopedName(
"moment"));
347 const auto&
U = lookupObject<volVectorField>(UName_);
349 if (foundObject<cmpTurbModel>(cmpTurbModel::propertiesName))
351 const cmpTurbModel&
turb =
352 lookupObject<cmpTurbModel>(cmpTurbModel::propertiesName);
354 return turb.devRhoReff(
U);
356 else if (foundObject<icoTurbModel>(icoTurbModel::propertiesName))
359 lookupObject<icoTurbModel>(icoTurbModel::propertiesName);
370 else if (foundObject<transportModel>(
"transportProperties"))
373 lookupObject<transportModel>(
"transportProperties");
377 else if (foundObject<dictionary>(
"transportProperties"))
380 lookupObject<dictionary>(
"transportProperties");
389 <<
"No valid model for viscous stress calculation"
406 else if (foundObject<transportModel>(
"transportProperties"))
409 lookupObject<transportModel>(
"transportProperties");
411 return rho()*laminarT.
nu();
413 else if (foundObject<dictionary>(
"transportProperties"))
416 lookupObject<dictionary>(
"transportProperties");
425 <<
"No valid model for dynamic viscosity calculation"
435 if (rhoName_ ==
"rhoInf")
442 mesh_.time().timeName(),
450 return(lookupObject<volScalarField>(rhoName_));
461 if (rhoName_ !=
"rhoInf")
464 <<
"Dynamic pressure is expected but kinematic is provided."
483 force_[0][0] +=
sum(fN);
484 force_[1][0] +=
sum(fT);
485 force_[2][0] +=
sum(fP);
486 moment_[0][0] +=
sum(Md^fN);
487 moment_[1][0] +=
sum(Md^fT);
488 moment_[2][0] +=
sum(Md^fP);
496 label bini =
min(
max(floor(dd[i]/binDx_), 0), force_[0].size() - 1);
498 force_[0][bini] += fN[i];
499 force_[1][bini] += fT[i];
500 force_[2][bini] += fP[i];
501 moment_[0][bini] += Md[i]^fN[i];
502 moment_[1][bini] += Md[i]^fT[i];
503 moment_[2][bini] += Md[i]^fP[i];
523 auto& force = lookupObjectRef<volVectorField>(scopedName(
"force"));
524 vectorField& pf = force.boundaryFieldRef()[patchi];
527 auto& moment = lookupObjectRef<volVectorField>(scopedName(
"moment"));
528 vectorField& pm = moment.boundaryFieldRef()[patchi];
547 auto& force = lookupObjectRef<volVectorField>(scopedName(
"force"));
548 auto& moment = lookupObjectRef<volVectorField>(scopedName(
"moment"));
552 label celli = cellIDs[i];
553 force[celli] += fN[i] + fT[i] + fP[i];
554 moment[celli] = Md[i]^force[celli];
561 const string& descriptor,
573 Log <<
" Sum of " << descriptor.c_str() <<
nl
574 <<
" Total : " << total <<
nl
576 <<
" Viscous : " << viscous <<
nl;
580 Log <<
" Porous : " << porous <<
nl;
587 writeCurrentTime(
os);
607 const auto& coordSys = coordSysPtr_();
609 writeIntegratedForceMoment
612 coordSys.localVector(force_[0]),
613 coordSys.localVector(force_[1]),
614 coordSys.localVector(force_[2]),
618 writeIntegratedForceMoment
621 coordSys.localVector(moment_[0]),
622 coordSys.localVector(moment_[1]),
623 coordSys.localVector(moment_[2]),
637 if ((nBin_ == 1) || !writeToFile())
646 for (label i = 1; i <
f[0].size(); i++)
648 f[0][i] +=
f[0][i-1];
649 f[1][i] +=
f[1][i-1];
650 f[2][i] +=
f[2][i-1];
656 writeCurrentTime(
os);
660 vector total =
f[0][i] +
f[1][i] +
f[2][i];
678 const auto& coordSys = coordSysPtr_();
682 lf[0] = coordSys.localVector(force_[0]);
683 lf[1] = coordSys.localVector(force_[1]);
684 lf[2] = coordSys.localVector(force_[2]);
685 lm[0] = coordSys.localVector(moment_[0]);
686 lm[1] = coordSys.localVector(moment_[1]);
687 lm[2] = coordSys.localVector(moment_[2]);
689 writeBinnedForceMoment(lf, forceBinFilePtr_);
690 writeBinnedForceMoment(lm, momentBinFilePtr_);
716 directForceDensity_(
false),
720 coordSysPtr_(
nullptr),
728 binCumulative_(
true),
735 setCoordinateSystem(
dict);
761 directForceDensity_(
false),
765 coordSysPtr_(
nullptr),
773 binCumulative_(
true),
780 setCoordinateSystem(
dict);
804 initialised_ =
false;
808 directForceDensity_ =
dict.getOrDefault(
"directForceDensity",
false);
811 mesh_.boundaryMesh().patchSet
816 if (directForceDensity_)
819 if (
dict.readIfPresent<
word>(
"fD", fDName_))
827 if (
dict.readIfPresent<
word>(
"p", pName_))
831 if (
dict.readIfPresent<
word>(
"U", UName_))
835 if (
dict.readIfPresent<
word>(
"rho", rhoName_))
837 Info<<
" rho: " << rhoName_ <<
endl;
841 if (rhoName_ ==
"rhoInf")
843 rhoRef_ =
dict.get<scalar>(
"rhoInf");
844 Info<<
" Freestream density (rhoInf) set to " << rhoRef_ <<
endl;
848 if (
dict.readIfPresent<scalar>(
"pRef", pRef_))
850 Info<<
" Reference pressure (pRef) set to " << pRef_ <<
endl;
854 dict.readIfPresent(
"porosity", porosity_);
857 Info<<
" Including porosity effects" <<
endl;
861 Info<<
" Not including porosity effects" <<
endl;
864 if (
dict.found(
"binData"))
866 Info<<
" Activated data bins" <<
endl;
868 nBin_ = binDict.
get<label>(
"nBin");
873 <<
"Number of bins (nBin) must be zero or greater"
883 Info<<
" Employing " << nBin_ <<
" bins" <<
endl;
884 if (binDict.readIfPresent(
"min", binMin_))
886 Info<<
" - min : " << binMin_ <<
endl;
888 if (binDict.readIfPresent(
"max", binMax_))
890 Info<<
" - max : " << binMax_ <<
endl;
893 binCumulative_ = binDict.get<
bool>(
"cumulative");
894 Info<<
" - cumuluative : " << binCumulative_ <<
endl;
896 binDir_ = binDict.get<
vector>(
"direction");
898 Info<<
" - direction : " << binDir_ <<
endl;
902 writeFields_ =
dict.getOrDefault(
"writeFields",
false);
906 Info<<
" Fields will be written" <<
endl;
925 mesh_.objectRegistry::store(forcePtr);
933 scopedName(
"moment"),
944 mesh_.objectRegistry::store(momentPtr);
957 const point& origin = coordSysPtr_->origin();
959 if (directForceDensity_)
963 const surfaceVectorField::Boundary& Sfb = mesh_.Sf().boundaryField();
965 for (
const label patchi : patchSet_)
967 vectorField Md(mesh_.C().boundaryField()[patchi] - origin);
986 addToFields(patchi, Md, fN, fT, fP);
988 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[patchi]);
995 const surfaceVectorField::Boundary& Sfb = mesh_.Sf().boundaryField();
998 const volSymmTensorField::Boundary& devRhoReffb
999 = tdevRhoReff().boundaryField();
1002 scalar pRef = pRef_/
rho(
p);
1004 for (
const label patchi : patchSet_)
1006 vectorField Md(mesh_.C().boundaryField()[patchi] - origin);
1010 rho(
p)*Sfb[patchi]*(
p.boundaryField()[patchi] - pRef)
1013 vectorField fT(Sfb[patchi] & devRhoReffb[patchi]);
1017 addToFields(patchi, Md, fN, fT, fP);
1019 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[patchi]);
1035 <<
"Porosity effects requested, but no porosity models found "
1036 <<
"in the database"
1049 for (
const label zonei : cellZoneIDs)
1051 const cellZone& cZone = mesh_.cellZones()[zonei];
1059 addToFields(cZone, Md, fDummy, fDummy, fP);
1061 applyBins(Md, fDummy, fDummy, fP, d);
1075 return sum(force_[0]) +
sum(force_[1]) +
sum(force_[2]);
1081 return sum(moment_[0]) +
sum(moment_[1]) +
sum(moment_[2]);
1101 setResult(
"normalForce",
sum(force_[0]));
1102 setResult(
"tangentialForce",
sum(force_[1]));
1103 setResult(
"porousForce",
sum(force_[2]));
1105 setResult(
"normalMoment",
sum(moment_[0]));
1106 setResult(
"tangentialMoment",
sum(moment_[1]));
1107 setResult(
"porousMoment",
sum(moment_[2]));
1117 lookupObject<volVectorField>(scopedName(
"force")).write();
1118 lookupObject<volVectorField>(scopedName(
"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.
autoPtr< OFstream > momentBinFilePtr_
Moment bins.
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.
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.
autoPtr< OFstream > forceFilePtr_
Forces.
autoPtr< OFstream > momentFilePtr_
Moments.
#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.
label nBin_
Number of bins.
void initialise()
Initialise the fields.
messageStream Info
Information stream (stdout output on master, null elsewhere)
A patch is a list of labels that address the faces in the global face list.
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.
autoPtr< OFstream > forceBinFilePtr_
Force bins.
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.
OBJstream os(runTime.globalPath()/outputName)
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.
virtual autoPtr< OFstream > createFile(const word &name, scalar timeValue) const
Return autoPtr to a new file for a given time.
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...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
static const Vector< scalar > 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.
virtual bool writeToFile() const
Flag to allow writing to file.
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)
word dictName() const
The local dictionary name (final part of scoped name)