67 else if (
dict.readIfPresent(
"CofR", origin))
78 coordSysPtr_.reset(
new coordSystem::cartesian(origin, e3, e1));
92 auto* ptr = mesh_.getObjectPtr<
volVectorField>(scopedName(
"force"));
120 auto* ptr = mesh_.getObjectPtr<
volVectorField>(scopedName(
"moment"));
128 scopedName(
"moment"),
153 if (directForceDensity_)
155 if (!foundObject<volVectorField>(fDName_))
158 <<
"Could not find " << fDName_ <<
" in database"
166 !foundObject<volVectorField>(UName_)
167 || !foundObject<volScalarField>(pName_)
171 <<
"Could not find U: " << UName_
172 <<
" or p:" << pName_ <<
" in database"
176 if (rhoName_ !=
"rhoInf" && !foundObject<volScalarField>(rhoName_))
179 <<
"Could not find rho:" << rhoName_ <<
" in database"
190 sumPatchForcesP_ =
Zero;
191 sumPatchForcesV_ =
Zero;
192 sumPatchMomentsP_ =
Zero;
193 sumPatchMomentsV_ =
Zero;
195 sumInternalForces_ =
Zero;
196 sumInternalMoments_ =
Zero;
198 auto& force = this->force();
199 auto& moment = this->moment();
208 for (
const label patchi : patchIDs_)
210 force.boundaryField().constCast()[patchi] =
Zero;
227 if (
const auto* turbp = cfindObject<icoModel>(icoModel::propertiesName))
229 const auto&
turb = *turbp;
234 if (
const auto* turbp = cfindObject<cmpModel>(cmpModel::propertiesName))
236 const auto&
turb = *turbp;
243 const auto&
thermo = *thermop;
248 if (
const auto* props = cfindObject<transportModel>(
"transportProperties"))
250 const auto& laminarT = *props;
255 if (
const auto* props = cfindObject<dictionary>(
"transportProperties"))
264 <<
"No valid model for viscous stress calculation"
275 const auto&
thermo = *thermop;
280 if (
const auto* props = cfindObject<transportModel>(
"transportProperties"))
282 const auto& laminarT = *props;
284 return rho()*laminarT.nu();
287 if (
const auto* props = cfindObject<dictionary>(
"transportProperties"))
296 <<
"No valid model for dynamic viscosity calculation"
305 if (rhoName_ ==
"rhoInf")
316 return lookupObject<volScalarField>(rhoName_);
323 if (rhoName_ ==
"rhoInf")
327 mesh_.boundary()[patchi].size(),
332 const auto&
rho = lookupObject<volScalarField>(rhoName_);
333 return rho.boundaryField()[patchi];
344 if (rhoName_ !=
"rhoInf")
347 <<
"Dynamic pressure is expected but kinematic is provided."
363 sumPatchForcesP_ +=
sum(fP);
364 sumPatchForcesV_ +=
sum(fV);
365 force().boundaryField().constCast()[patchi] += fP + fV;
372 moment().boundaryField().constCast()[patchi] += mP + mV;
383 auto& force = this->force();
384 auto& moment = this->moment();
388 const label celli = cellIDs[i];
390 sumInternalForces_ +=
f[i];
391 force[celli] +=
f[i];
404 forceFilePtr_ = newFileAtStartTime(
"force");
405 writeIntegratedDataFileHeader(
"Force", forceFilePtr_());
422 const auto& coordSys = coordSysPtr_();
423 const auto vecDesc = [](
const word& root)->
string
425 return root +
"_x " + root +
"_y " + root +
"_z";
428 writeHeaderValue(
os,
"CofR", coordSys.origin());
430 writeCommented(
os,
"Time");
431 writeTabbed(
os, vecDesc(
"total"));
432 writeTabbed(
os, vecDesc(
"pressure"));
433 writeTabbed(
os, vecDesc(
"viscous"));
446 const auto& coordSys = coordSysPtr_();
448 writeIntegratedDataFile
450 coordSys.localVector(sumPatchForcesP_),
451 coordSys.localVector(sumPatchForcesV_),
452 coordSys.localVector(sumInternalForces_),
456 writeIntegratedDataFile
458 coordSys.localVector(sumPatchMomentsP_),
474 writeCurrentTime(
os);
476 writeValue(
os, pres + vis + internal);
477 writeValue(
os, pres);
491 const string& descriptor,
502 Log <<
" Sum of " << descriptor.c_str() <<
nl
503 <<
" Total : " << (pres + vis + internal) <<
nl
504 <<
" Pressure : " << pres <<
nl
505 <<
" Viscous : " << vis <<
nl;
509 Log <<
" Porous : " << internal <<
nl;
525 writeFile(mesh_,
name),
526 sumPatchForcesP_(
Zero),
527 sumPatchForcesV_(
Zero),
528 sumPatchMomentsP_(
Zero),
529 sumPatchMomentsV_(
Zero),
530 sumInternalForces_(
Zero),
531 sumInternalMoments_(
Zero),
534 coordSysPtr_(nullptr),
541 directForceDensity_(false),
563 fvMeshFunctionObject(
name, obr,
dict),
564 writeFile(mesh_,
name),
565 sumPatchForcesP_(
Zero),
566 sumPatchForcesV_(
Zero),
567 sumPatchMomentsP_(
Zero),
568 sumPatchMomentsV_(
Zero),
569 sumInternalForces_(
Zero),
570 sumInternalMoments_(
Zero),
573 coordSysPtr_(nullptr),
580 directForceDensity_(false),
610 patchIDs_ =
pbm.patchSet(
dict.get<wordRes>(
"patches")).sortedToc();
612 dict.readIfPresent(
"directForceDensity", directForceDensity_);
613 if (directForceDensity_)
616 if (
dict.readIfPresent<word>(
"fD", fDName_))
624 if (
dict.readIfPresent<word>(
"p", pName_))
628 if (
dict.readIfPresent<word>(
"U", UName_))
632 if (
dict.readIfPresent<word>(
"rho", rhoName_))
634 Info<<
" rho: " << rhoName_ <<
endl;
638 if (rhoName_ ==
"rhoInf")
641 Info<<
" Freestream density (rhoInf) set to " << rhoRef_ <<
endl;
645 if (
dict.readIfPresent<scalar>(
"pRef", pRef_))
647 Info<<
" Reference pressure (pRef) set to " << pRef_ <<
endl;
651 dict.readIfPresent(
"porosity", porosity_);
654 Info<<
" Including porosity effects" <<
endl;
658 Info<<
" Not including porosity effects" <<
endl;
661 writeFields_ =
dict.getOrDefault(
"writeFields",
false);
664 Info<<
" Fields will be written" <<
endl;
678 const point& origin = coordSysPtr_->origin();
680 if (directForceDensity_)
682 const auto& fD = lookupObject<volVectorField>(fDName_);
683 const auto& fDb = fD.boundaryField();
685 const auto& Sfb = mesh_.Sf().boundaryField();
686 const auto& magSfb = mesh_.magSf().boundaryField();
687 const auto&
Cb = mesh_.C().boundaryField();
689 for (
const label patchi : patchIDs_)
696 Sfb[patchi]/magSfb[patchi]
698 Sfb[patchi] & fDb[patchi]
703 const vectorField fV(magSfb[patchi]*fDb[patchi] - fP);
705 addToPatchFields(patchi, Md, fP, fV);
710 const auto&
p = lookupObject<volScalarField>(pName_);
711 const auto& pb =
p.boundaryField();
713 const auto& Sfb = mesh_.Sf().boundaryField();
714 const auto&
Cb = mesh_.C().boundaryField();
716 const auto&
U = lookupObject<volVectorField>(UName_);
719 const auto& gradUb = gradU.boundaryField();
722 const scalar rhoRef =
rho(
p);
723 const scalar pRef = pRef_/rhoRef;
725 for (
const label patchi : patchIDs_)
729 const vectorField fP(rhoRef*Sfb[patchi]*(pb[patchi] - pRef));
733 Sfb[patchi] & devRhoReff(gradUb[patchi], patchi)
736 addToPatchFields(patchi, Md, fP, fV);
742 const auto&
U = lookupObject<volVectorField>(UName_);
746 const UPtrList<const porosityModel> models
748 obr_.csorted<porosityModel>()
754 <<
"Porosity effects requested, "
755 <<
"but no porosity models found in the database"
759 for (
const porosityModel& mdl : models)
762 auto& pm =
const_cast<porosityModel&
>(mdl);
766 const labelList& cellZoneIDs = pm.cellZoneIDs();
768 for (
const label zonei : cellZoneIDs)
770 const cellZone& cZone = mesh_.cellZones()[zonei];
776 addToInternalField(cZone, Md, fP);
781 reduce(sumPatchForcesP_, sumOp<vector>());
782 reduce(sumPatchForcesV_, sumOp<vector>());
808 const auto& coordSys = coordSysPtr_();
810 const auto localFp(coordSys.localVector(sumPatchForcesP_));
811 const auto localFv(coordSys.localVector(sumPatchForcesV_));
812 const auto localFi(coordSys.localVector(sumInternalForces_));
814 logIntegratedData(
"forces", localFp, localFv, localFi);
816 const auto localMp(coordSys.localVector(sumPatchMomentsP_));
817 const auto localMv(coordSys.localVector(sumPatchMomentsV_));
818 const auto localMi(coordSys.localVector(sumInternalMoments_));
820 logIntegratedData(
"moments", localMp, localMv, localMi);
822 setResult(
"pressureForce", localFp);
823 setResult(
"viscousForce", localFv);
824 setResult(
"internalForce", localFi);
825 setResult(
"pressureMoment", localMp);
837 Log <<
" writing force and moment files." <<
endl;
839 createIntegratedDataFiles();
840 writeIntegratedDataFiles();
845 Log <<
" writing force and moment fields." <<
endl;
CGAL::indexedCell< K > Cb
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
const polyBoundaryMesh & pbm
compressible::turbulenceModel & turb
static tmp< GeometricField< scalar, fvPatchField, volMesh > > New(const word &name, IOobjectOption::registerOption regOpt, const Mesh &mesh, const dimensionSet &dims, const word &patchFieldType=fvPatchField< scalar >::calculatedType())
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
@ NO_REGISTER
Do not request registration (bool: false).
@ REGISTER
Request registration (bool: true).
@ NO_READ
Nothing to be read.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
static MinMax< scalar > ge(const scalar &minVal)
Output to file stream as an OSstream, normally using std::ofstream for the actual output.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
bool empty() const noexcept
True if the list is empty (ie, size() is zero).
static const word dictName
The dictionary name ("thermophysicalProperties").
A Cartesian coordinate system.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Abstract base-class for Time/database function objects.
virtual bool read(const dictionary &dict)
Read and set the function object if its data have changed.
word scopedName(const word &name) const
Return a scoped (prefixed) name.
Computes forces and moments over a given list of patches by integrating pressure and viscous forces a...
virtual void calcForcesMoments()
Calculate forces and moments.
void writeIntegratedDataFileHeader(const word &header, OFstream &os) const
Write header for an integrated-data file.
word pName_
Name of pressure field.
scalar rhoRef_
Reference density needed for incompressible calculations.
bool porosity_
Flag to include porosity effects.
void initialise()
Initialise containers and fields.
void addToPatchFields(const label patchi, const vectorField &Md, const vectorField &fP, const vectorField &fV)
Add patch contributions to force and moment fields.
bool directForceDensity_
Flag to directly supply force density.
word UName_
Name of velocity field.
vector sumPatchForcesV_
Sum of patch viscous forces.
void writeIntegratedDataFiles()
Write integrated data to files.
vector sumPatchForcesP_
Sum of patch pressure forces.
vector sumInternalMoments_
Sum of internal moments.
volVectorField & moment()
Return access to the moment field.
void createIntegratedDataFiles()
Create the integrated-data files.
bool initialised_
Flag of initialisation (internal).
autoPtr< OFstream > forceFilePtr_
File stream for forces.
vector sumPatchMomentsV_
Sum of patch viscous moments.
tmp< volScalarField > mu() const
Return dynamic viscosity field.
vector sumInternalForces_
Sum of internal forces.
forces(const word &name, const Time &runTime, const dictionary &dict, const bool readFields=true)
Construct from name, Time and dictionary.
virtual vector forceEff() const
Return the total force.
void logIntegratedData(const string &descriptor, const vector &pres, const vector &vis, const vector &internal) const
Write integrated data to stream.
autoPtr< coordinateSystem > coordSysPtr_
Coordinate system used when evaluating forces and moments.
virtual vector momentEff() const
Return the total moment.
void addToInternalField(const labelList &cellIDs, const vectorField &Md, const vectorField &f)
Add cell contributions to force and moment fields, and include porosity effects.
autoPtr< OFstream > momentFilePtr_
File stream for moments.
vector sumPatchMomentsP_
Sum of patch pressure moments.
word rhoName_
Name of density field.
void writeIntegratedDataFile(const vector &pres, const vector &vis, const vector &internal, OFstream &os) const
Write integrated data to a file.
tmp< symmTensorField > devRhoReff(const tensorField &gradUp, const label patchi) const
Return the effective stress (viscous + turbulent) for patch.
bool writeFields_
Flag to write force and moment fields.
tmp< volScalarField > rho() const
Return rho if specified otherwise rhoRef.
void reset()
Reset containers and fields.
virtual bool execute()
Execute the function-object operations.
volVectorField & force()
Return access to the force field.
virtual bool write()
Write the function-object results.
scalar pRef_
Reference pressure.
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.
word fDName_
Name of force density field.
labelList patchIDs_
Selected operand patches.
virtual bool read(const dictionary &)
Read the function-object dictionary.
const fvMesh & mesh_
Reference to the fvMesh.
fvMeshFunctionObject(const fvMeshFunctionObject &)=delete
No copy construct.
Computes the natural logarithm of an input volScalarField.
Reads fields from the time directories and adds them to the mesh database for further post-processing...
const ObjectType & lookupObject(const word &fieldName) const
Lookup and return object (eg, a field) from the (sub) objectRegistry.
const ObjectType * cfindObject(const word &fieldName) const
Return const pointer to the object (eg, a field) in the (sub) objectRegistry.
bool foundObject(const word &fieldName) const
Find object (eg, a field) in the (sub) objectRegistry.
const objectRegistry & obr_
Reference to the region objectRegistry.
virtual const objectRegistry & obr() const
The region or sub-region registry being used.
void setResult(const word &entryName, const Type &value)
Add result.
const Time & time_
Reference to the time database.
virtual autoPtr< OFstream > newFileAtStartTime(const word &name) const
Return autoPtr to a new file using the simulation start time.
virtual void writeTabbed(Ostream &os, const string &str) const
Write a tabbed string to stream.
void writeHeaderValue(Ostream &os, const string &property, const Type &value) const
Write a (commented) header property and value pair.
writeFile(const objectRegistry &obr, const fileName &prefix, const word &name="undefined", const bool writeToFile=true, const string &ext=".dat")
Construct from objectRegistry, prefix, fileName.
virtual bool read(const dictionary &dict)
Read.
void writeValue(Ostream &os, const Type &val) const
Write a given value to stream with the space delimiter.
virtual void writeCommented(Ostream &os, const string &str) const
Write a commented string to stream.
virtual void writeCurrentTime(Ostream &os) const
Write the current time to stream.
virtual bool writeToFile() const
Flag to allow writing to file.
Registry of regIOobjects.
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
Top level model for porosity models.
bool store()
Register object with its registry and transfer ownership to the registry.
Basic thermodynamics type based on the use of fitting functions for cp, h, s obtained from the templa...
A class for managing temporary objects.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
A List of wordRe with additional matching capabilities.
A class for handling words, derived from Foam::string.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
limits reset(1/(limits.max()+VSMALL), 1/(limits.min()+VSMALL))
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
OBJstream os(runTime.globalPath()/outputName)
Calculate the gradient of the given field.
#define WarningInFunction
Report a warning using Foam::Warning.
ThermalDiffusivity< CompressibleTurbulenceModel< fluidThermo > > turbulenceModel
Function objects are OpenFOAM utilities to ease workflow configurations and enhance workflows.
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh > > grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
IncompressibleTurbulenceModel< transportModel > turbulenceModel
const dimensionSet dimPressure
const dimensionSet dimViscosity
GeometricField< vector, fvPatchField, volMesh > volVectorField
void readFields(const typename GeoFieldType::Mesh &mesh, const IOobjectList &objects, const NameMatchPredicate &selectedFields, DynamicList< regIOobject * > &storedObjects)
Read the selected GeometricFields of the templated type and store on the objectRegistry.
List< label > labelList
A List of labels.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
GeometricField< scalar, fvPatchField, volMesh > volScalarField
SymmTensor< Cmpt > devTwoSymm(const SymmTensor< Cmpt > &st)
Return the deviatoric part of twice the symmetric part of a SymmTensor.
static void writeHeader(Ostream &os, const word &fieldName)
messageStream Info
Information stream (stdout output on master, null elsewhere).
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
dimensionedScalar log(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
GeometricField< tensor, fvPatchField, volMesh > volTensorField
void reduce(T &value, BinaryOp bop, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce).
const dimensionSet dimForce
Field< vector > vectorField
Specialisation of Field<T> for vector.
vector point
Point is a vector.
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &f1, const label comm)
static constexpr const zero Zero
Global zero (0).
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
const dimensionSet dimDensity
errorManipArg< error, int > exit(error &err, const int errNo=1)
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
constexpr char nl
The newline '\n' character (0x0a).
static bool initialised_(false)
psiReactionThermo & thermo
#define forAll(list, i)
Loop across all elements in list.