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_
217 const word phaseModelName =
222 if (obr_.foundObject<icoModel>(
modelName))
229 else if (obr_.foundObject<cmpModel>(
modelName))
231 const cmpModel& model =
236 else if (obr_.foundObject<phaseIcoModel>(phaseModelName))
238 const phaseIcoModel& model =
239 obr_.lookupObject<phaseIcoModel>(phaseModelName);
243 else if (obr_.foundObject<phaseCmpModel>(phaseModelName))
245 const phaseCmpModel& model =
246 obr_.lookupObject<phaseCmpModel>(phaseModelName);
248 return model.devTau();
253 <<
"No valid model for viscous stress calculation"
269 const word phaseModelName =
274 if (obr_.foundObject<icoModel>(
modelName))
279 return rho()*model.
nu();
281 else if (obr_.foundObject<cmpModel>(
modelName))
283 const cmpModel& model =
286 return model.rho()*model.nu();
288 else if (obr_.foundObject<phaseIcoModel>(phaseModelName))
290 const phaseIcoModel& model =
291 obr_.lookupObject<phaseIcoModel>(phaseModelName);
293 return rho()*model.nu();
295 else if (obr_.foundObject<phaseCmpModel>(phaseModelName))
297 const phaseCmpModel& model =
298 obr_.lookupObject<phaseCmpModel>(phaseModelName);
300 return model.rho()*model.nu();
302 else if (obr_.foundObject<
dictionary>(
"physicalProperties"))
307 obr_.lookupObject<
dictionary>(
"physicalProperties");
321 <<
"No valid model for dynamic viscosity calculation"
331 if (rhoName_ ==
"rhoInf")
358 if (rhoName_ !=
"rhoInf")
361 <<
"Dynamic pressure is expected but kinematic is provided."
408 ).boundaryField()[
patchi];
424 force_[0][0] +=
sum(fN);
425 force_[1][0] +=
sum(fT);
426 force_[2][0] +=
sum(fP);
427 moment_[0][0] +=
sum(Md^fN);
428 moment_[1][0] +=
sum(Md^fT);
429 moment_[2][0] +=
sum(Md^fP);
437 label bini =
min(
max(floor(dd[i]/binDx_), 0), force_[0].size() - 1);
439 force_[0][bini] += fN[i];
440 force_[1][bini] += fT[i];
441 force_[2][bini] += fP[i];
442 moment_[0][bini] += Md[i]^fN[i];
443 moment_[1][bini] += Md[i]^fT[i];
444 moment_[2][bini] += Md[i]^fP[i];
469 <<
" sum of forces:" <<
nl
470 <<
" pressure : " <<
sum(force_[0]) <<
nl
471 <<
" viscous : " <<
sum(force_[1]) <<
nl
472 <<
" porous : " <<
sum(force_[2]) <<
nl
473 <<
" sum of moments:" <<
nl
474 <<
" pressure : " <<
sum(moment_[0]) <<
nl
475 <<
" viscous : " <<
sum(moment_[1]) <<
nl
476 <<
" porous : " <<
sum(moment_[2])
479 writeTime(
file(fileID::mainFile));
480 writeCofR(
file(fileID::mainFile));
485 <<
sum(force_[0]) <<
setw(1) <<
' '
486 <<
sum(force_[1]) <<
setw(1) <<
' '
487 <<
sum(force_[2]) <<
setw(3) <<
") ("
488 <<
sum(moment_[0]) <<
setw(1) <<
' '
489 <<
sum(moment_[1]) <<
setw(1) <<
' '
490 <<
sum(moment_[2]) <<
setw(1) <<
')';
495 <<
sum(force_[0]) <<
setw(1) <<
' '
496 <<
sum(force_[1]) <<
setw(3) <<
") ("
497 <<
sum(moment_[0]) <<
setw(1) <<
' '
498 <<
sum(moment_[1]) <<
setw(1) <<
')';
517 for (
label i = 1; i <
f[0].size(); i++)
519 f[0][i] +=
f[0][i-1];
520 f[1][i] +=
f[1][i-1];
521 f[2][i] +=
f[2][i-1];
523 m[0][i] += m[0][i-1];
524 m[1][i] += m[1][i-1];
525 m[2][i] += m[2][i-1];
529 writeTime(
file(fileID::binsFile));
536 file(fileID::binsFile)
538 <<
f[0][i] <<
setw(1) <<
' '
539 <<
f[1][i] <<
setw(1) <<
' '
540 <<
f[2][i] <<
setw(3) <<
") ("
541 << m[0][i] <<
setw(1) <<
' '
542 << m[1][i] <<
setw(1) <<
' '
543 << m[2][i] <<
setw(1) <<
')';
547 file(fileID::binsFile)
549 <<
f[0][i] <<
setw(1) <<
' '
550 <<
f[1][i] <<
setw(3) <<
") ("
551 << m[0][i] <<
setw(1) <<
' '
552 << m[1][i] <<
setw(1) <<
')';
576 rhoName_(
word::null),
577 phaseName_(
word::null),
578 directForceDensity_(false),
588 binCumulative_(true),
609 rhoName_(
word::null),
610 phaseName_(
word::null),
611 directForceDensity_(false),
621 binCumulative_(true),
640 initialised_ =
false;
644 directForceDensity_ =
dict.lookupOrDefault(
"directForceDensity",
false);
650 if (directForceDensity_)
653 fDName_ =
dict.lookupOrDefault<
word>(
"fD",
"fD");
681 if (rhoName_ ==
"rhoInf")
683 dict.lookup(
"rhoInf") >> rhoRef_;
687 pRef_ =
dict.lookupOrDefault<scalar>(
"pRef", 0.0);
690 dict.readIfPresent(
"porosity", porosity_);
693 Log <<
" Including porosity effects" <<
endl;
697 Log <<
" Not including porosity effects" <<
endl;
700 if (
dict.found(
"binData"))
703 binDict.
lookup(
"nBin") >> nBin_;
708 <<
"Number of bins (nBin) must be zero or greater"
711 else if ((nBin_ == 0) || (nBin_ == 1))
716 force_[i].setSize(1);
717 moment_[i].setSize(1);
723 binDict.
lookup(
"direction") >> binDir_;
724 binDir_ /=
mag(binDir_);
727 scalar binMax = -great;
733 binMin_ =
min(
min(d), binMin_);
734 binMax =
max(
max(d), binMax);
741 binMax = 1.0001*(binMax - binMin_) + binMin_;
743 binDx_ = (binMax - binMin_)/scalar(nBin_);
746 binPoints_.setSize(nBin_);
749 binPoints_[i] = (i + 0.5)*binDir_*binDx_;
752 binDict.
lookup(
"cumulative") >> binCumulative_;
757 force_[i].setSize(nBin_);
758 moment_[i].setSize(nBin_);
766 force_[0].setSize(1);
767 force_[1].setSize(1);
768 force_[2].setSize(1);
769 moment_[0].setSize(1);
770 moment_[1].setSize(1);
771 moment_[2].setSize(1);
774 resetNames(createFileNames(
dict));
792 if (directForceDensity_)
797 mesh_.Sf().boundaryField();
805 mesh_.C().boundaryField()[
patchi] - CofR
825 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[
patchi]);
833 mesh_.Sf().boundaryField();
836 mesh_.magSf().boundaryField();
842 const scalar pRef = pRef_/
rho(
p);
850 mesh_.C().boundaryField()[
patchi] - CofR
858 *(
p.boundaryField()[
patchi] - pRef)
865 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[
patchi]);
881 <<
"Porosity effects requested, but no porosity models found "
899 applyBins(Md, fDummy, fDummy, fP, d);
918 return sum(force_[0]) +
sum(force_[1]) +
sum(force_[2]);
924 return sum(moment_[0]) +
sum(moment_[1]) +
sum(moment_[2]);
936 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 turbulence 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 turbulence 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 turbulence models.
Templated abstract base class for multiphase incompressible turbulence 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(adjustTimeStepToCombustion, 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)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
const dimensionSet dimPressure
Ostream & endl(Ostream &os)
Add newline and flush stream.
const dimensionSet dimKinematicViscosity
Omanip< int > setw(const int i)
errorManip< error > abort(error &err)
const dimensionSet dimless
void mag(LagrangianPatchField< scalar > &f, const LagrangianPatchField< Type > &f1)
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
const dimensionSet dimDensity
dimensionedScalar jn(const int n, const dimensionedScalar &ds)
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
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.