34 #include "surfaceInterpolate.H"
41 namespace functionObjects
57 const word forceType(
dict.lookup(
"type"));
62 if (
dict.found(
"binData"))
82 ?
"(pressure viscous porous)"
83 :
"(pressure viscous)"
88 case fileID::mainFile:
93 writeCoRValueHeader(
file(i));
94 writeCommented(
file(i),
"Time");
96 writeCoRHeader(
file(i));
99 <<
"forces" << forceTypes <<
tab
100 <<
"moments" << forceTypes;
104 case fileID::binsFile:
109 writeHeaderValue(
file(i),
"bins", nBin_);
110 writeHeaderValue(
file(i),
"start", binMin_);
111 writeHeaderValue(
file(i),
"delta", binDx_);
112 writeHeaderValue(
file(i),
"direction", binDir_);
115 writeCommented(
file(i),
"x co-ords :");
118 binPoints[pointi] = (binMin_ + (pointi + 1)*binDx_)*binDir_;
119 file(i) <<
tab << binPoints[pointi].x();
123 writeCommented(
file(i),
"y co-ords :");
126 file(i) <<
tab << binPoints[pointi].y();
130 writeCommented(
file(i),
"z co-ords :");
133 file(i) <<
tab << binPoints[pointi].z();
137 writeCommented(
file(i),
"Time");
139 for (
label j = 0; j < nBin_; j++)
142 const word f(
"forces" +
jn + forceTypes);
143 const word m(
"moments" +
jn + forceTypes);
153 <<
"Unhandled file index: " << i
169 if (directForceDensity_)
174 <<
"Could not find " << fDName_ <<
" in database."
188 <<
"Could not find " << UName_ <<
", " << pName_
199 <<
"Could not find " << rhoName_
221 if (rhoName_ !=
"rhoInf")
224 <<
"Dynamic pressure is expected but kinematic is provided."
271 ).boundaryField()[
patchi];
287 force_[0][0] +=
sum(fN);
288 force_[1][0] +=
sum(fT);
289 force_[2][0] +=
sum(fP);
290 moment_[0][0] +=
sum(Md^fN);
291 moment_[1][0] +=
sum(Md^fT);
292 moment_[2][0] +=
sum(Md^fP);
300 label bini =
min(
max(floor(dd[i]/binDx_), 0), force_[0].size() - 1);
302 force_[0][bini] += fN[i];
303 force_[1][bini] += fT[i];
304 force_[2][bini] += fP[i];
305 moment_[0][bini] += Md[i]^fN[i];
306 moment_[1][bini] += Md[i]^fT[i];
307 moment_[2][bini] += Md[i]^fP[i];
332 <<
" sum of forces:" <<
nl
333 <<
" pressure : " <<
sum(force_[0]) <<
nl
334 <<
" viscous : " <<
sum(force_[1]) <<
nl
335 <<
" porous : " <<
sum(force_[2]) <<
nl
336 <<
" sum of moments:" <<
nl
337 <<
" pressure : " <<
sum(moment_[0]) <<
nl
338 <<
" viscous : " <<
sum(moment_[1]) <<
nl
339 <<
" porous : " <<
sum(moment_[2])
342 writeTime(
file(fileID::mainFile));
343 writeCofR(
file(fileID::mainFile));
348 <<
sum(force_[0]) <<
setw(1) <<
' '
349 <<
sum(force_[1]) <<
setw(1) <<
' '
350 <<
sum(force_[2]) <<
setw(3) <<
") ("
351 <<
sum(moment_[0]) <<
setw(1) <<
' '
352 <<
sum(moment_[1]) <<
setw(1) <<
' '
353 <<
sum(moment_[2]) <<
setw(1) <<
')';
358 <<
sum(force_[0]) <<
setw(1) <<
' '
359 <<
sum(force_[1]) <<
setw(3) <<
") ("
360 <<
sum(moment_[0]) <<
setw(1) <<
' '
361 <<
sum(moment_[1]) <<
setw(1) <<
')';
380 for (
label i = 1; i <
f[0].size(); i++)
382 f[0][i] +=
f[0][i-1];
383 f[1][i] +=
f[1][i-1];
384 f[2][i] +=
f[2][i-1];
386 m[0][i] += m[0][i-1];
387 m[1][i] += m[1][i-1];
388 m[2][i] += m[2][i-1];
392 writeTime(
file(fileID::binsFile));
399 file(fileID::binsFile)
401 <<
f[0][i] <<
setw(1) <<
' '
402 <<
f[1][i] <<
setw(1) <<
' '
403 <<
f[2][i] <<
setw(3) <<
") ("
404 << m[0][i] <<
setw(1) <<
' '
405 << m[1][i] <<
setw(1) <<
' '
406 << m[2][i] <<
setw(1) <<
')';
410 file(fileID::binsFile)
412 <<
f[0][i] <<
setw(1) <<
' '
413 <<
f[1][i] <<
setw(3) <<
") ("
414 << m[0][i] <<
setw(1) <<
' '
415 << m[1][i] <<
setw(1) <<
')';
439 rhoName_(
word::null),
440 phaseName_(
word::null),
441 directForceDensity_(false),
451 binCumulative_(true),
472 rhoName_(
word::null),
473 phaseName_(
word::null),
474 directForceDensity_(false),
484 binCumulative_(true),
503 initialised_ =
false;
507 directForceDensity_ =
dict.lookupOrDefault(
"directForceDensity",
false);
513 if (directForceDensity_)
516 fDName_ =
dict.lookupOrDefault<
word>(
"fD",
"fD");
544 if (rhoName_ ==
"rhoInf")
546 dict.lookup(
"rhoInf") >> rhoRef_;
550 pRef_ =
dict.lookupOrDefault<scalar>(
"pRef", 0.0);
553 dict.readIfPresent(
"porosity", porosity_);
556 Log <<
" Including porosity effects" <<
endl;
560 Log <<
" Not including porosity effects" <<
endl;
563 if (
dict.found(
"binData"))
566 binDict.
lookup(
"nBin") >> nBin_;
571 <<
"Number of bins (nBin) must be zero or greater"
574 else if ((nBin_ == 0) || (nBin_ == 1))
579 force_[i].setSize(1);
580 moment_[i].setSize(1);
586 binDict.
lookup(
"direction") >> binDir_;
587 binDir_ /=
mag(binDir_);
590 scalar binMax = -great;
596 binMin_ =
min(
min(d), binMin_);
597 binMax =
max(
max(d), binMax);
604 binMax = 1.0001*(binMax - binMin_) + binMin_;
606 binDx_ = (binMax - binMin_)/scalar(nBin_);
609 binPoints_.setSize(nBin_);
612 binPoints_[i] = (i + 0.5)*binDir_*binDx_;
615 binDict.
lookup(
"cumulative") >> binCumulative_;
620 force_[i].setSize(nBin_);
621 moment_[i].setSize(nBin_);
629 force_[0].setSize(1);
630 force_[1].setSize(1);
631 force_[2].setSize(1);
632 moment_[0].setSize(1);
633 moment_[1].setSize(1);
634 moment_[2].setSize(1);
637 resetNames(createFileNames(
dict));
651 const word phaseModelName =
656 if (obr_.foundObject<icoModel>(
modelName))
663 else if (obr_.foundObject<cmpModel>(
modelName))
665 const cmpModel& model =
670 else if (obr_.foundObject<phaseIcoModel>(phaseModelName))
672 const phaseIcoModel& model =
673 obr_.lookupObject<phaseIcoModel>(phaseModelName);
677 else if (obr_.foundObject<phaseCmpModel>(phaseModelName))
679 const phaseCmpModel& model =
680 obr_.lookupObject<phaseCmpModel>(phaseModelName);
682 return model.devTau();
687 <<
"No valid model for viscous stress calculation"
703 const word phaseModelName =
708 if (obr_.foundObject<icoModel>(
modelName))
713 return rho()*model.
nu();
715 else if (obr_.foundObject<cmpModel>(
modelName))
717 const cmpModel& model =
720 return model.rho()*model.nu();
722 else if (obr_.foundObject<phaseIcoModel>(phaseModelName))
724 const phaseIcoModel& model =
725 obr_.lookupObject<phaseIcoModel>(phaseModelName);
727 return rho()*model.nu();
729 else if (obr_.foundObject<phaseCmpModel>(phaseModelName))
731 const phaseCmpModel& model =
732 obr_.lookupObject<phaseCmpModel>(phaseModelName);
734 return model.rho()*model.nu();
736 else if (obr_.foundObject<
dictionary>(
"physicalProperties"))
741 obr_.lookupObject<
dictionary>(
"physicalProperties");
755 <<
"No valid model for dynamic viscosity calculation"
765 if (rhoName_ ==
"rhoInf")
793 if (directForceDensity_)
798 mesh_.Sf().boundaryField();
806 mesh_.C().boundaryField()[
patchi] - CofR
826 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[
patchi]);
834 mesh_.Sf().boundaryField();
837 mesh_.magSf().boundaryField();
843 const scalar pRef = pRef_/
rho(
p);
851 mesh_.C().boundaryField()[
patchi] - CofR
859 *(
p.boundaryField()[
patchi] - pRef)
866 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[
patchi]);
882 <<
"Porosity effects requested, but no porosity models found "
900 applyBins(Md, fDummy, fDummy, fP, d);
919 return sum(force_[0]) +
sum(force_[1]) +
sum(force_[2]);
925 return sum(moment_[0]) +
sum(moment_[1]) +
sum(moment_[2]);
937 calcForcesMoments(CofR());
#define forAll(list, i)
Loop across all elements in list.
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Macros for easy insertion into run-time selection tables.
Generic GeometricBoundaryField class.
Generic GeometricField class.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
static const GeometricField< Type, GeoMesh, PrimitiveField > & null()
Return a null geometric field.
static tmp< GeometricField< Type, GeoMesh, PrimitiveField > > New(const word &name, const Internal &, const PtrList< Patch > &, const HashPtrTable< Source > &=HashPtrTable< Source >())
Return a temporary field constructed from name,.
An STL-conforming hash table.
bool empty() const
Return true if the hash table is empty.
static word groupName(Name name, const word &group)
void append(const T &)
Append an element at the end of the list.
void size(const label)
Override size to be inconsistent with allocated storage.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
static bool master(const label communicator=0)
Am I the master process.
Named list of cell indices representing a sub-set of the mesh.
Base class for single-phase compressible momentum transport models.
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Calculates the forces and moments by integrating the pressure and skin-friction forces over a given l...
virtual void calcForcesMoments()
Calculate the forces and moments.
tmp< volScalarField > alpha() const
Get the volume fraction field.
void initialise()
Initialise the fields.
virtual void writeCoRHeader(Ostream &file)
Write the time varying centre of rotation column header.
tmp< surfaceVectorField > devTau() const
Return the effective surface stress.
void applyBins(const vectorField &Md, const vectorField &fN, const vectorField &fT, const vectorField &fP, const vectorField &d)
Accumulate bin data.
tmp< volScalarField > mu() const
Dynamic viscosity field.
virtual vector forceEff() const
Return the total force.
forcesBase(const word &name, const Time &runTime, const dictionary &dict)
Construct from Time and dictionary.
virtual vector momentEff() const
Return the total moment.
virtual void writeCoRValueHeader(Ostream &file)
Write the constant centre of rotation value in the header.
void writeBins()
Helper function to write bin data.
virtual ~forcesBase()
Destructor.
virtual void writeFileHeader(const label i)
Output file header information.
void writeForces()
Helper function to write force data.
tmp< volScalarField > rho() const
Return rho if specified otherwise rhoRef.
fileID
Enumeration for ensuring the right file is accessed.
virtual bool execute()
Execute, currently does nothing.
virtual bool write()
Write the forces.
virtual void writeCofR(Ostream &file)
Write the time varying centre of rotation.
virtual bool read(const dictionary &)
Read the forces data.
wordList createFileNames(const dictionary &dict) const
Create file names for forces and bins.
Specialisation of Foam::functionObject for an Foam::fvMesh, providing a reference to the Foam::fvMesh...
functionObject base class for creating, maintaining and writing log files e.g. integrated of averaged...
const wordList & names() const
Return the list of log file names.
virtual bool write()
Write function.
virtual bool read(const dictionary &)
Read optional controls.
Base class for single-phase incompressible momentum transport models.
virtual tmp< surfaceVectorField > devSigma() const
Return the effective surface stress.
virtual tmp< volScalarField > nu() const
Return the laminar viscosity.
Registry of regIOobjects.
Templated abstract base class for multiphase compressible momentum transport models.
Templated abstract base class for multiphase incompressible momentum transport models.
A base class for physical properties.
labelHashSet patchSet(const UList< wordRe > &patchNames, const bool warnNotFound=true, const bool usePatchGroups=true) const
Return the patch set corresponding to the given names.
A patch is a list of labels that address the faces in the global face list.
const vectorField::subField faceCentres() const
Return face centres.
Top level model for porosity models.
const word & zoneName() const
Return const access to the cell zone name.
virtual tmp< vectorField > force(const volVectorField &U, const volScalarField &rho, const volScalarField &mu) const
Return the force over the cell zone(s)
A class for managing temporary objects.
A class for handling words, derived from string.
static const word null
An empty word.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Calculate the gradient of the given field.
volScalarField alpha(IOobject("alpha", runTime.name(), mesh, IOobject::READ_IF_PRESENT, IOobject::AUTO_WRITE), lambda *max(Ua &U, zeroSensitivity))
#define WarningInFunction
Report a warning using Foam::Warning.
#define Log
Report write to Foam::Info if the local log switch is true.
const dimensionedScalar mu
Atomic mass unit.
defineTypeNameAndDebug(fvMeshFunctionObject, 0)
static tmp< SurfaceField< Type > > interpolate(const VolField< Type > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
void writeHeader(std::ostream &, const bool isBinary, const std::string &title)
Write header.
errorManipArg< error, int > exit(error &err, const int errNo=1)
const dimensionSet & dimless
const dimensionSet & dimKinematicViscosity
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Omanip< int > setw(const int i)
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
errorManip< error > abort(error &err)
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
const dimensionSet & dimDensity
tmp< DimensionedField< scalar, GeoMesh, Field > > jn(const int n, const DimensionedField< scalar, GeoMesh, PrimitiveField > &dsf)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
const dimensionSet & dimPressure
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.