41 namespace functionObjects
67 else if (
dict.readIfPresent(
"CofR", origin))
78 coordSysPtr_.reset(
new coordSystem::cartesian(origin, e3, e1));
92 auto* forcePtr = mesh_.getObjectPtr<
volVectorField>(scopedName(
"force"));
110 mesh_.objectRegistry::store(forcePtr);
119 auto* momentPtr = mesh_.getObjectPtr<
volVectorField>(scopedName(
"moment"));
127 scopedName(
"moment"),
137 mesh_.objectRegistry::store(momentPtr);
151 if (directForceDensity_)
153 if (!foundObject<volVectorField>(fDName_))
156 <<
"Could not find " << fDName_ <<
" in database" 164 !foundObject<volVectorField>(UName_)
165 || !foundObject<volScalarField>(pName_)
169 <<
"Could not find U: " << UName_
170 <<
" or p:" << pName_ <<
" in database" 174 if (rhoName_ !=
"rhoInf" && !foundObject<volScalarField>(rhoName_))
177 <<
"Could not find rho:" << rhoName_ <<
" in database" 188 sumPatchForcesP_ =
Zero;
189 sumPatchForcesV_ =
Zero;
190 sumPatchMomentsP_ =
Zero;
191 sumPatchMomentsV_ =
Zero;
193 sumInternalForces_ =
Zero;
194 sumInternalMoments_ =
Zero;
196 auto& force = this->force();
197 auto& moment = this->moment();
209 if (foundObject<cmpTurbModel>(cmpTurbModel::propertiesName))
212 lookupObject<cmpTurbModel>(cmpTurbModel::propertiesName);
214 return turb.devRhoReff();
216 else if (foundObject<icoTurbModel>(icoTurbModel::propertiesName))
219 lookupObject<icoTurbModel>(icoTurbModel::propertiesName);
227 const auto&
U = lookupObject<volVectorField>(UName_);
231 else if (foundObject<transportModel>(
"transportProperties"))
233 const auto& laminarT =
234 lookupObject<transportModel>(
"transportProperties");
236 const auto&
U = lookupObject<volVectorField>(UName_);
240 else if (foundObject<dictionary>(
"transportProperties"))
243 lookupObject<dictionary>(
"transportProperties");
247 const auto&
U = lookupObject<volVectorField>(UName_);
254 <<
"No valid model for viscous stress calculation" 270 else if (foundObject<transportModel>(
"transportProperties"))
272 const auto& laminarT =
273 lookupObject<transportModel>(
"transportProperties");
275 return rho()*laminarT.nu();
277 else if (foundObject<dictionary>(
"transportProperties"))
280 lookupObject<dictionary>(
"transportProperties");
289 <<
"No valid model for dynamic viscosity calculation" 299 if (rhoName_ ==
"rhoInf")
306 mesh_.time().timeName(),
314 return (lookupObject<volScalarField>(rhoName_));
325 if (rhoName_ !=
"rhoInf")
328 <<
"Dynamic pressure is expected but kinematic is provided." 344 sumPatchForcesP_ +=
sum(fP);
345 sumPatchForcesV_ +=
sum(fV);
346 force().boundaryFieldRef()[patchi] += fP + fV;
351 sumPatchMomentsP_ +=
sum(mP);
352 sumPatchMomentsV_ +=
sum(mV);
353 moment().boundaryFieldRef()[patchi] += mP + mV;
364 auto& force = this->force();
365 auto& moment = this->moment();
369 const label celli =
cellIDs[i];
371 sumInternalForces_ +=
f[i];
372 force[celli] +=
f[i];
375 sumInternalMoments_ += m;
383 if (!forceFilePtr_.valid())
385 forceFilePtr_ = newFileAtStartTime(
"force");
386 writeIntegratedDataFileHeader(
"Force", forceFilePtr_());
389 if (!momentFilePtr_.valid())
391 momentFilePtr_ = newFileAtStartTime(
"moment");
392 writeIntegratedDataFileHeader(
"Moment", momentFilePtr_());
403 const auto& coordSys = coordSysPtr_();
404 const auto vecDesc = [](
const word& root)->
string 406 return root +
"_x " + root +
"_y " + root +
"_z";
409 writeHeaderValue(
os,
"CofR", coordSys.origin());
411 writeCommented(
os,
"Time");
412 writeTabbed(
os, vecDesc(
"total"));
413 writeTabbed(
os, vecDesc(
"pressure"));
414 writeTabbed(
os, vecDesc(
"viscous"));
418 writeTabbed(
os, vecDesc(
"porous"));
427 const auto& coordSys = coordSysPtr_();
429 writeIntegratedDataFile
431 coordSys.localVector(sumPatchForcesP_),
432 coordSys.localVector(sumPatchForcesV_),
433 coordSys.localVector(sumInternalForces_),
437 writeIntegratedDataFile
439 coordSys.localVector(sumPatchMomentsP_),
440 coordSys.localVector(sumPatchMomentsV_),
441 coordSys.localVector(sumInternalMoments_),
455 writeCurrentTime(
os);
457 writeValue(
os, pres + vis +
internal);
458 writeValue(
os, pres);
463 writeValue(
os,
internal);
472 const string& descriptor,
483 Log <<
" Sum of " << descriptor.c_str() <<
nl 484 <<
" Total : " << (pres + vis +
internal) <<
nl 485 <<
" Pressure : " << pres <<
nl 486 <<
" Viscous : " << vis <<
nl;
490 Log <<
" Porous : " <<
internal <<
nl;
506 writeFile(mesh_,
name),
507 sumPatchForcesP_(
Zero),
508 sumPatchForcesV_(
Zero),
509 sumPatchMomentsP_(
Zero),
510 sumPatchMomentsV_(
Zero),
511 sumInternalForces_(
Zero),
512 sumInternalMoments_(
Zero),
515 coordSysPtr_(nullptr),
523 directForceDensity_(false),
545 fvMeshFunctionObject(
name, obr,
dict),
546 writeFile(mesh_,
name),
547 sumPatchForcesP_(
Zero),
548 sumPatchForcesV_(
Zero),
549 sumPatchMomentsP_(
Zero),
550 sumPatchMomentsV_(
Zero),
551 sumInternalForces_(
Zero),
552 sumInternalMoments_(
Zero),
555 coordSysPtr_(nullptr),
563 directForceDensity_(false),
586 initialised_ =
false;
591 mesh_.boundaryMesh().patchSet
593 dict.get<wordRes>(
"patches")
596 dict.readIfPresent(
"directForceDensity", directForceDensity_);
597 if (directForceDensity_)
600 if (
dict.readIfPresent<word>(
"fD", fDName_))
608 if (
dict.readIfPresent<word>(
"p", pName_))
612 if (
dict.readIfPresent<word>(
"U", UName_))
616 if (
dict.readIfPresent<word>(
"rho", rhoName_))
618 Info<<
" rho: " << rhoName_ <<
endl;
622 if (rhoName_ ==
"rhoInf")
625 Info<<
" Freestream density (rhoInf) set to " << rhoRef_ <<
endl;
629 if (
dict.readIfPresent<scalar>(
"pRef", pRef_))
631 Info<<
" Reference pressure (pRef) set to " << pRef_ <<
endl;
635 dict.readIfPresent(
"porosity", porosity_);
638 Info<<
" Including porosity effects" <<
endl;
642 Info<<
" Not including porosity effects" <<
endl;
645 writeFields_ =
dict.getOrDefault(
"writeFields",
false);
648 Info<<
" Fields will be written" <<
endl;
662 const point& origin = coordSysPtr_->origin();
664 if (directForceDensity_)
666 const auto& fD = lookupObject<volVectorField>(fDName_);
668 const auto& Sfb = mesh_.Sf().boundaryField();
670 for (
const label patchi : patchSet_)
672 const vectorField& d = mesh_.C().boundaryField()[patchi];
683 Sfb[patchi] & fD.boundaryField()[patchi]
688 const vectorField fV(sA*fD.boundaryField()[patchi] - fP);
690 addToPatchFields(patchi, Md, fP, fV);
695 const auto&
p = lookupObject<volScalarField>(pName_);
697 const auto& Sfb = mesh_.Sf().boundaryField();
699 tmp<volSymmTensorField> tdevRhoReff = devRhoReff();
700 const auto& devRhoReffb = tdevRhoReff().boundaryField();
703 const scalar rhoRef =
rho(
p);
704 const scalar pRef = pRef_/rhoRef;
706 for (
const label patchi : patchSet_)
708 const vectorField& d = mesh_.C().boundaryField()[patchi];
714 rhoRef*Sfb[patchi]*(
p.boundaryField()[patchi] - pRef)
717 const vectorField fV(Sfb[patchi] & devRhoReffb[patchi]);
719 addToPatchFields(patchi, Md, fP, fV);
725 const auto&
U = lookupObject<volVectorField>(UName_);
729 const auto models = obr_.lookupClass<porosityModel>();
734 <<
"Porosity effects requested, " 735 <<
"but no porosity models found in the database" 742 auto& pm =
const_cast<porosityModel&
>(*iter());
746 const labelList& cellZoneIDs = pm.cellZoneIDs();
748 for (
const label zonei : cellZoneIDs)
750 const cellZone& cZone = mesh_.cellZones()[zonei];
756 addToInternalField(cZone, Md, fP);
761 reduce(sumPatchForcesP_, sumOp<vector>());
762 reduce(sumPatchForcesV_, sumOp<vector>());
772 return sumPatchForcesP_ + sumPatchForcesV_ + sumInternalForces_;
778 return sumPatchMomentsP_ + sumPatchMomentsV_ + sumInternalMoments_;
788 const auto& coordSys = coordSysPtr_();
790 const auto localFp(coordSys.localVector(sumPatchForcesP_));
791 const auto localFv(coordSys.localVector(sumPatchForcesV_));
792 const auto localFi(coordSys.localVector(sumInternalForces_));
794 logIntegratedData(
"forces", localFp, localFv, localFi);
796 const auto localMp(coordSys.localVector(sumPatchMomentsP_));
797 const auto localMv(coordSys.localVector(sumPatchMomentsV_));
798 const auto localMi(coordSys.localVector(sumInternalMoments_));
800 logIntegratedData(
"moments", localMp, localMv, localMi);
802 setResult(
"pressureForce", localFp);
803 setResult(
"viscousForce", localFv);
804 setResult(
"internalForce", localFi);
805 setResult(
"pressureMoment", localMp);
806 setResult(
"viscousMoment", localMv);
807 setResult(
"internalMoment", localMi);
817 Log <<
" writing force and moment files." <<
endl;
819 createIntegratedDataFiles();
820 writeIntegratedDataFiles();
825 Log <<
" writing force and moment fields." <<
endl;
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
virtual vector momentEff() const
Return the total moment.
word dictName() const
The local dictionary name (final part of scoped name)
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
defineTypeNameAndDebug(ObukhovLength, 0)
static void writeHeader(Ostream &os, const word &fieldName)
dimensionedScalar log(const dimensionedScalar &ds)
errorManipArg< error, int > exit(error &err, const int errNo=1)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Output to file stream, using an OSstream.
constexpr char nl
The newline '\n' character (0x0a)
const dimensionSet dimViscosity
compressible::turbulenceModel & turb
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
Ostream & endl(Ostream &os)
Add newline and flush stream.
volVectorField & force()
Return access to the force field.
virtual vector forceEff() const
Return the total force.
Ignore writing from objectRegistry::writeObject()
Templated wrapper class to provide compressible turbulence models thermal diffusivity based thermal t...
GeometricField< vector, fvPatchField, volMesh > volVectorField
void addToPatchFields(const label patchi, const vectorField &Md, const vectorField &fP, const vectorField &fV)
Add patch contributions to force and moment fields.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
virtual bool read(const dictionary &dict)
Read the dictionary.
void writeIntegratedDataFiles()
Write integrated data to files.
Macros for easy insertion into run-time selection tables.
dimensionedSymmTensor twoSymm(const dimensionedSymmTensor &dt)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
void writeIntegratedDataFile(const vector &pres, const vector &vis, const vector &internal, OFstream &os) const
Write integrated data to a file.
#define forAll(list, i)
Loop across all elements in list.
A Cartesian coordinate system.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
psiReactionThermo & thermo
Templated abstract base class for single-phase incompressible turbulence models.
virtual bool execute()
Execute the function object.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
virtual void calcForcesMoments()
Calculate forces and moments.
dimensionedSymmTensor dev(const dimensionedSymmTensor &dt)
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Calculate the gradient of the given field.
A class for handling words, derived from Foam::string.
tmp< volScalarField > mu() const
Return dynamic viscosity field.
static MinMax< scalar > ge(const scalar &minVal)
A semi-infinite range from minVal to the type max.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
IOdictionary transportProperties(IOobject("transportProperties", runTime.constant(), mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
void addToInternalField(const labelList &cellIDs, const vectorField &Md, const vectorField &f)
Add cell contributions to force and moment fields, and include porosity effects.
tmp< volScalarField > rho() const
Return rho if specified otherwise rhoRef.
const dimensionSet & dimensions() const noexcept
Return const reference to dimensions.
const dimensionSet dimPressure
void createIntegratedDataFiles()
Create the integrated-data files.
volVectorField & moment()
Return access to the moment field.
Basic thermodynamics type based on the use of fitting functions for cp, h, s obtained from the templa...
const dimensionSet dimForce
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
tmp< volSymmTensorField > devRhoReff() const
Return the effective stress (viscous + turbulent)
void reset()
Reset containers and fields.
void initialise()
Initialise containers and fields.
OBJstream os(runTime.globalPath()/outputName)
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
virtual bool read(const dictionary &dict)
Read.
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.
const dimensionSet dimDensity
static const GeometricField< symmTensor, fvPatchField, volMesh > & null()
Return a null geometric field.
const dimensionedScalar mu
Atomic mass unit.
autoPtr< coordinateSystem > coordSysPtr_
Coordinate system used when evaluating forces and moments.
#define WarningInFunction
Report a warning using Foam::Warning.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
forces(const word &name, const Time &runTime, const dictionary &dict, const bool readFields=true)
Construct from Time and dictionary.
const objectRegistry & obr_
Reference to the region objectRegistry.
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual bool read(const dictionary &dict)
Read optional controls.
Field< vector > vectorField
Specialisation of Field<T> for vector.
void readFields(const typename GeoFieldType::Mesh &mesh, const IOobjectList &objects, const wordHashSet &selectedFields, LIFOStack< regIOobject *> &storedObjects)
Read the selected GeometricFields of the templated type.
List< label > labelList
A List of labels.
A class for managing temporary objects.
void writeIntegratedDataFileHeader(const word &header, OFstream &os) const
Write header for an integrated-data file.
Registry of regIOobjects.
Defines the attributes of an object for which implicit objectRegistry management is supported...
void logIntegratedData(const string &descriptor, const vector &pres, const vector &vis, const vector &internal) const
Write integrated data to stream.
virtual bool write()
Write to data files/fields and to streams.
forAllConstIters(mixture.phases(), phase)
static constexpr const zero Zero
Global zero (0)