35#include "porosityModel.H"
36#include "turbulentTransportModel.H"
37#include "turbulentFluidThermoModel.H"
38#include "addToRunTimeSelectionTable.H"
39#include "cartesianCS.H"
45namespace functionObjects
56 const word& name)
const
58 return this->name() +
":" + name;
65 if (writeToFile() && !forceFilePtr_.valid())
67 forceFilePtr_ = createFile(
"force");
68 writeIntegratedHeader(
"Force", forceFilePtr_());
69 momentFilePtr_ = createFile(
"moment");
70 writeIntegratedHeader(
"Moment", momentFilePtr_());
74 forceBinFilePtr_ = createFile(
"forceBin");
75 writeBinHeader(
"Force", forceBinFilePtr_());
76 momentBinFilePtr_ = createFile(
"momentBin");
77 writeBinHeader(
"Moment", momentBinFilePtr_());
82 localForceFilePtr_ = createFile(
"localForce");
83 writeIntegratedHeader(
"Force", localForceFilePtr_());
84 localMomentFilePtr_ = createFile(
"localMoment");
85 writeIntegratedHeader(
"Moment", localMomentFilePtr_());
89 localForceBinFilePtr_ = createFile(
"localForceBin");
90 writeBinHeader(
"Force", localForceBinFilePtr_());
91 localMomentBinFilePtr_ = createFile(
"localMomentBin");
92 writeBinHeader(
"Moment", localMomentBinFilePtr_());
105 writeHeader(os, header);
106 writeHeaderValue(os,
"CofR", coordSys_.origin());
108 writeCommented(os,
"Time");
109 writeTabbed(os,
"(total_x total_y total_z)");
110 writeTabbed(os,
"(pressure_x pressure_y pressure_z)");
111 writeTabbed(os,
"(viscous_x viscous_y viscous_z)");
115 writeTabbed(os,
"(porous_x porous_y porous_z)");
128 writeHeader(os, header +
" bins");
129 writeHeaderValue(os,
"bins", nBin_);
130 writeHeaderValue(os,
"start", binMin_);
131 writeHeaderValue(os,
"delta", binDx_);
132 writeHeaderValue(os,
"direction", binDir_);
133 vectorField binPoints(nBin_);
134 writeCommented(os,
"x co-ords :");
137 binPoints[pointi] = (binMin_ + (pointi + 1) * binDx_) * binDir_;
138 os << tab << binPoints[pointi].x();
141 writeCommented(os,
"y co-ords :");
144 os << tab << binPoints[pointi].y();
147 writeCommented(os,
"z co-ords :");
150 os << tab << binPoints[pointi].z();
154 writeCommented(os,
"Time");
156 for (label j = 0; j < nBin_; j++)
158 const word jn(Foam::name(j) +
':');
159 os << tab << jn <<
"(total_x total_y total_z)"
160 << tab << jn <<
"(pressure_x pressure_y pressure_z)"
161 << tab << jn <<
"(viscous_x viscous_y viscous_z)";
165 os << tab << jn <<
"(porous_x porous_y porous_z)";
181 if (directForceDensity_)
183 if (!foundObject<volVectorField>(fDName_))
186 <<
"Could not find " << fDName_ <<
" in database"
194 !foundObject<volVectorField>(UName_)
195 || !foundObject<volScalarField>(pName_)
199 <<
"Could not find U: " << UName_ <<
" or p:" << pName_
204 if (rhoName_ !=
"rhoInf" && !foundObject<volScalarField>(rhoName_))
207 <<
"Could not find rho:" << rhoName_
221 const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
224 scalar binMax = -GREAT;
226 for (
const label patchi : patchSet_)
228 const polyPatch& pp = pbm[patchi];
229 scalarField d(pp.faceCentres() & binDir_);
230 binMin_ =
min(
min(d), binMin_);
231 binMax =
max(
max(d), binMax);
237 const HashTable<const porosityModel*> models =
238 obr_.lookupClass<porosityModel>();
239 const scalarField dd(mesh_.C() & binDir_);
240 forAllConstIter(HashTable<const porosityModel*>, models, iter)
242 const porosityModel& pm = *iter();
243 const labelList& cellZoneIDs = pm.cellZoneIDs();
245 for (
const label zonei : cellZoneIDs)
247 const cellZone& cZone = mesh_.cellZones()[zonei];
248 const scalarField d(dd, cZone);
249 binMin_ =
min(
min(d), binMin_);
250 binMax =
max(
max(d), binMax);
255 reduce(binMin_, minOp<scalar>());
256 reduce(binMax, maxOp<scalar>());
259 binMax = 1.0001 * (binMax - binMin_) + binMin_;
260 binDx_ = (binMax - binMin_) / scalar(nBin_);
262 binPoints_.setSize(nBin_);
265 binPoints_[
i] = (
i + 0.5) * binDir_ * binDx_;
272 force_[
i].setSize(nBin_, vector::zero);
273 moment_[
i].setSize(nBin_, vector::zero);
289 volVectorField& force =
290 lookupObjectRef<volVectorField>(fieldName(
"force"));
291 force == dimensionedVector(force.dimensions(), Zero);
292 volVectorField& moment =
293 lookupObjectRef<volVectorField>(fieldName(
"moment"));
294 moment == dimensionedVector(moment.dimensions(), Zero);
299Foam::tmp<Foam::volSymmTensorField>
302 typedef compressible::turbulenceModel cmpTurbModel;
303 typedef incompressible::turbulenceModel icoTurbModel;
305 if (foundObject<cmpTurbModel>(cmpTurbModel::propertiesName))
307 const cmpTurbModel& turb =
308 lookupObject<cmpTurbModel>(cmpTurbModel::propertiesName);
309 return turb.devRhoReff();
311 else if (foundObject<icoTurbModel>(icoTurbModel::propertiesName))
313 const incompressible::turbulenceModel& turb =
314 lookupObject<icoTurbModel>(icoTurbModel::propertiesName);
315 return rho() * turb.devReff();
317 else if (foundObject<fluidThermo>(fluidThermo::dictName))
319 const fluidThermo& thermo =
320 lookupObject<fluidThermo>(fluidThermo::dictName);
321 const volVectorField&
U = lookupObject<volVectorField>(UName_);
322 return -thermo.mu() * dev(twoSymm(fvc::grad(
U)));
324 else if (foundObject<transportModel>(
"transportProperties"))
326 const transportModel& laminarT =
327 lookupObject<transportModel>(
"transportProperties");
328 const volVectorField&
U = lookupObject<volVectorField>(UName_);
329 return -rho() * laminarT.nu() * dev(twoSymm(fvc::grad(
U)));
331 else if (foundObject<dictionary>(
"transportProperties"))
334 lookupObject<dictionary>(
"transportProperties");
336 const volVectorField&
U = lookupObject<volVectorField>(UName_);
337 return -rho() *
nu * dev(twoSymm(fvc::grad(
U)));
342 <<
"No valid model for viscous stress calculation"
344 return volSymmTensorField::null();
351 if (foundObject<fluidThermo>(basicThermo::dictName))
353 const fluidThermo& thermo =
354 lookupObject<fluidThermo>(basicThermo::dictName);
357 else if (foundObject<transportModel>(
"transportProperties"))
359 const transportModel& laminarT =
360 lookupObject<transportModel>(
"transportProperties");
361 return rho() * laminarT.nu();
363 else if (foundObject<dictionary>(
"transportProperties"))
366 lookupObject<dictionary>(
"transportProperties");
378 <<
"No valid model for dynamic viscosity calculation"
380 return volScalarField::null();
387 if (rhoName_ ==
"rhoInf")
389 return tmp<volScalarField>::New
394 mesh_.time().timeName(),
398 dimensionedScalar(
"rho", dimDensity, rhoRef_)
402 return (lookupObject<volScalarField>(rhoName_));
409 if (
p.dimensions() == dimPressure)
414 if (rhoName_ !=
"rhoInf")
417 <<
"Dynamic pressure is expected but kinematic is provided."
427 const vectorField& Md,
428 const vectorField& fN,
429 const vectorField& fT,
430 const vectorField& fP,
436 force_[0][0] += sum(fN);
437 force_[1][0] += sum(fT);
438 force_[2][0] += sum(fP);
439 moment_[0][0] += sum(Md ^ fN);
440 moment_[1][0] += sum(Md ^ fT);
441 moment_[2][0] += sum(Md ^ fP);
445 scalarField dd((d & binDir_) - binMin_);
448 label bini =
min(
max(floor(dd[
i] / binDx_), 0), force_[0].size() - 1);
449 force_[0][bini] += fN[
i];
450 force_[1][bini] += fT[
i];
451 force_[2][bini] += fP[
i];
452 moment_[0][bini] += Md[
i] ^ fN[
i];
453 moment_[1][bini] += Md[
i] ^ fT[
i];
454 moment_[2][bini] += Md[
i] ^ fP[
i];
463 const vectorField& Md,
464 const vectorField& fN,
465 const vectorField& fT,
466 const vectorField& fP
474 volVectorField& force =
475 lookupObjectRef<volVectorField>(fieldName(
"force"));
476 vectorField& pf = force.boundaryFieldRef()[patchi];
478 volVectorField& moment =
479 lookupObjectRef<volVectorField>(fieldName(
"moment"));
480 vectorField& pm = moment.boundaryFieldRef()[patchi];
487 const labelList& cellIDs,
488 const vectorField& Md,
489 const vectorField& fN,
490 const vectorField& fT,
491 const vectorField& fP
499 volVectorField& force =
500 lookupObjectRef<volVectorField>(fieldName(
"force"));
501 volVectorField& moment =
502 lookupObjectRef<volVectorField>(fieldName(
"moment"));
505 label celli = cellIDs[
i];
506 force[celli] += fN[
i] + fT[
i] + fP[
i];
507 moment[celli] += Md[
i];
514 const string& descriptor,
515 const vectorField& fm0,
516 const vectorField& fm1,
517 const vectorField& fm2,
518 autoPtr<OFstream>& osPtr
521 vector pressure = sum(fm0);
522 vector viscous = sum(fm1);
523 vector porous = sum(fm2);
524 vector total = pressure + viscous + porous;
525 Log <<
" Sum of " << descriptor.c_str() << nl
526 <<
" Total : " << total << nl
527 <<
" Pressure : " << pressure << nl
528 <<
" Viscous : " << viscous << nl;
532 Log <<
" Porous : " << porous << nl;
537 Ostream& os = osPtr();
539 writeCurrentTime(os);
559 Log << type() <<
" " << name() <<
" write:" << nl;
560 writeIntegratedForceMoment
568 writeIntegratedForceMoment
579 writeIntegratedForceMoment
582 coordSys_.localVector(force_[0]),
583 coordSys_.localVector(force_[1]),
584 coordSys_.localVector(force_[2]),
587 writeIntegratedForceMoment
590 coordSys_.localVector(moment_[0]),
591 coordSys_.localVector(moment_[1]),
592 coordSys_.localVector(moment_[2]),
603 const List<Field<vector>>& fm,
604 autoPtr<OFstream>& osPtr
607 if ((nBin_ == 1) || !writeToFile())
612 List<Field<vector>> f(fm);
616 for (label
i = 1;
i < f[0].size();
i++)
618 f[0][
i] += f[0][
i - 1];
619 f[1][
i] += f[1][
i - 1];
620 f[2][
i] += f[2][
i - 1];
624 Ostream& os = osPtr();
626 writeCurrentTime(os);
632 vector total = f[0][
i] + f[1][
i] + f[2][
i];
639 os << tab << f[2][
i];
648 writeBinnedForceMoment(force_, forceBinFilePtr_);
649 writeBinnedForceMoment(moment_, momentBinFilePtr_);
653 List<Field<vector>> lf(3);
654 List<Field<vector>> lm(3);
655 lf[0] = coordSys_.localVector(force_[0]);
656 lf[1] = coordSys_.localVector(force_[1]);
657 lf[2] = coordSys_.localVector(force_[2]);
658 lm[0] = coordSys_.localVector(moment_[0]);
659 lm[1] = coordSys_.localVector(moment_[1]);
660 lm[2] = coordSys_.localVector(moment_[2]);
661 writeBinnedForceMoment(lf, localForceBinFilePtr_);
662 writeBinnedForceMoment(lm, localMomentBinFilePtr_);
673 const dictionary& dict,
677 fvMeshFunctionObject(name,
runTime, dict),
678 writeFile(mesh_, name),
685 localForceFilePtr_(),
686 localMomentFilePtr_(),
687 localForceBinFilePtr_(),
688 localMomentBinFilePtr_(),
692 rhoName_(word::null),
693 directForceDensity_(false),
705 binCumulative_(true),
720 const objectRegistry& obr,
721 const dictionary& dict,
725 fvMeshFunctionObject(name, obr, dict),
726 writeFile(mesh_, name),
733 localForceFilePtr_(),
734 localMomentFilePtr_(),
735 localForceBinFilePtr_(),
736 localMomentBinFilePtr_(),
740 rhoName_(word::null),
741 directForceDensity_(false),
753 binCumulative_(true),
786 fvMeshFunctionObject::read(dict);
787 writeFile::read(dict);
788 initialised_ =
false;
789 Info << type() <<
" " << name() <<
":" << nl;
790 directForceDensity_ = dict.lookupOrDefault(
"directForceDensity",
false);
791 const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
792 patchSet_ = pbm.patchSet(dict.get<wordRes>(
"patches"));
794 if (directForceDensity_)
797 fDName_ = dict.lookupOrDefault<word>(
"fD",
"fD");
802 pName_ = dict.lookupOrDefault<word>(
"p",
"p");
803 UName_ = dict.lookupOrDefault<word>(
"U",
"U");
804 rhoName_ = dict.lookupOrDefault<word>(
"rho",
"rho");
807 if (rhoName_ ==
"rhoInf")
809 dict.readEntry(
"rhoInf", rhoRef_);
813 pRef_ = dict.lookupOrDefault<scalar>(
"pRef", 0.0);
817 localSystem_ =
false;
821 if (!dict.readIfPresent<point>(
"CofR", coordSys_.origin()))
825 if (dict.found(coordinateSystem::typeName_()))
829 coordinateSystem::New
831 obr_, dict, coordinateSystem::typeName_()
836 coordSys_ = coordSystem::cartesian(dict);
842 dict.readIfPresent(
"porosity", porosity_);
846 Info <<
" Including porosity effects" << endl;
850 Info <<
" Not including porosity effects" << endl;
853 if (dict.found(
"binData"))
855 const dictionary& binDict(dict.subDict(
"binData"));
856 binDict.readEntry(
"nBin", nBin_);
860 FatalIOErrorInFunction(dict)
861 <<
"Number of bins (nBin) must be zero or greater"
862 << exit(FatalIOError);
871 binDict.readEntry(
"cumulative", binCumulative_);
872 binDict.readEntry(
"direction", binDir_);
877 writeFields_ = dict.lookupOrDefault(
"writeFields",
false);
881 Info <<
" Fields will be written" << endl;
882 volVectorField* forcePtr
895 dimensionedVector(dimForce, Zero)
898 mesh_.objectRegistry::store(forcePtr);
899 volVectorField* momentPtr
912 dimensionedVector(dimForce * dimLength, Zero)
915 mesh_.objectRegistry::store(momentPtr);
927 if (directForceDensity_)
929 const volVectorField& fD = lookupObject<volVectorField>(fDName_);
930 const surfaceVectorField::Boundary& Sfb = mesh_.Sf().boundaryField();
932 for (
const label patchi : patchSet_)
936 mesh_.C().boundaryField()[patchi] - coordSys_.origin()
938 scalarField sA(mag(Sfb[patchi]));
944 Sfb[patchi] & fD.boundaryField()[patchi]
948 vectorField fT(sA * fD.boundaryField()[patchi] - fN);
950 vectorField fP(Md.size(), Zero);
951 addToFields(patchi, Md, fN, fT, fP);
952 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[patchi]);
957 const volScalarField&
p = lookupObject<volScalarField>(pName_);
958 const surfaceVectorField::Boundary& Sfb = mesh_.Sf().boundaryField();
959 tmp<volSymmTensorField> tdevRhoReff = devRhoReff();
960 const volSymmTensorField::Boundary& devRhoReffb
961 = tdevRhoReff().boundaryField();
963 scalar pRef = pRef_ / rho(
p);
965 for (
const label patchi : patchSet_)
969 mesh_.C().boundaryField()[patchi] - coordSys_.origin()
973 rho(
p)*Sfb[patchi] * (
p.boundaryField()[patchi] - pRef)
975 vectorField fT(Sfb[patchi] & devRhoReffb[patchi]);
976 vectorField fP(Md.size(), Zero);
977 addToFields(patchi, Md, fN, fT, fP);
978 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[patchi]);
984 const volVectorField&
U = lookupObject<volVectorField>(UName_);
985 const volScalarField rho(this->rho());
986 const volScalarField mu(this->mu());
987 const HashTable<const porosityModel*> models =
988 obr_.lookupClass<porosityModel>();
993 <<
"Porosity effects requested, but no porosity models found "
998 forAllConstIters(models, iter)
1001 porosityModel& pm =
const_cast<porosityModel&
>(*iter());
1002 vectorField fPTot(pm.force(
U, rho, mu));
1003 const labelList& cellZoneIDs = pm.cellZoneIDs();
1005 for (
const label zonei : cellZoneIDs)
1007 const cellZone& cZone = mesh_.cellZones()[zonei];
1008 const vectorField d(mesh_.C(), cZone);
1009 const vectorField fP(fPTot, cZone);
1010 const vectorField Md(d - coordSys_.origin());
1011 const vectorField fDummy(Md.size(), Zero);
1012 addToFields(cZone, Md, fDummy, fDummy, fP);
1013 applyBins(Md, fDummy, fDummy, fP, d);
1018 Pstream::listCombineGather(force_, plusEqOp<vectorField>());
1019 Pstream::listCombineGather(moment_, plusEqOp<vectorField>());
1020 Pstream::listCombineScatter(force_);
1021 Pstream::listCombineScatter(moment_);
1027 return sum(force_[0]) + sum(force_[1]) + sum(force_[2]);
1033 return sum(moment_[0]) + sum(moment_[1]) + sum(moment_[2]);
1041 if (Pstream::master())
1050 setResult(
"normalForce", sum(force_[0]));
1051 setResult(
"tangentialForce", sum(force_[1]));
1052 setResult(
"porousForce", sum(force_[2]));
1053 setResult(
"normalMoment", sum(moment_[0]));
1054 setResult(
"tangentialMoment", sum(moment_[1]));
1055 setResult(
"porousMoment", sum(moment_[2]));
1064 lookupObject<volVectorField>(fieldName(
"force")).write();
1065 lookupObject<volVectorField>(fieldName(
"moment")).write();
1074 return sum(force_[0]);
1079 return sum(force_[1]);
1090#include "porosityModel.H"
1091#include "turbulentTransportModel.H"
1092#include "turbulentFluidThermoModel.H"
1093#include "addToRunTimeSelectionTable.H"
1099namespace functionObjects
1112 const dictionary& dict
1115 DynamicList<word> names(1);
1116 const word forceType(dict.lookup(
"type"));
1118 names.append(forceType);
1120 if (dict.found(
"binData"))
1122 const dictionary& binDict(dict.subDict(
"binData"));
1123 label nb = readLabel(binDict.lookup(
"nBin"));
1128 names.append(forceType +
"_bins");
1143 writeHeader(file(
i),
"Forces");
1144 writeHeaderValue(file(
i),
"CofR", coordSys_.origin());
1145 writeCommented(file(
i),
"Time");
1146 const word forceTypes(
"(pressure viscous porous)");
1148 <<
"forces" << forceTypes << tab
1149 <<
"moments" << forceTypes;
1155 <<
"localForces" << forceTypes << tab
1156 <<
"localMoments" << forceTypes;
1165 writeHeader(file(
i),
"Force bins");
1166 writeHeaderValue(file(
i),
"bins", nBin_);
1167 writeHeaderValue(file(
i),
"start", binMin_);
1168 writeHeaderValue(file(
i),
"delta", binDx_);
1169 writeHeaderValue(file(
i),
"direction", binDir_);
1170 vectorField binPoints(nBin_);
1171 writeCommented(file(
i),
"x co-ords :");
1172 forAll(binPoints, pointi)
1174 binPoints[pointi] = (binMin_ + (pointi + 1) * binDx_) * binDir_;
1175 file(
i) << tab << binPoints[pointi].x();
1178 writeCommented(file(
i),
"y co-ords :");
1179 forAll(binPoints, pointi)
1181 file(
i) << tab << binPoints[pointi].y();
1184 writeCommented(file(
i),
"z co-ords :");
1185 forAll(binPoints, pointi)
1187 file(
i) << tab << binPoints[pointi].z();
1190 writeCommented(file(
i),
"Time");
1191 const word binForceTypes(
"[pressure,viscous,porous]");
1193 for (label j = 0; j < nBin_; j++)
1195 const word jn(
'(' + Foam::name(j) +
')');
1196 const word f(
"forces" + jn + binForceTypes);
1197 const word m(
"moments" + jn + binForceTypes);
1198 file(
i) << tab << f << tab << m;
1203 for (label j = 0; j < nBin_; j++)
1205 const word jn(
'(' + Foam::name(j) +
')');
1206 const word f(
"localForces" + jn + binForceTypes);
1207 const word m(
"localMoments" + jn + binForceTypes);
1208 file(
i) << tab << f << tab << m;
1217 FatalErrorInFunction
1218 <<
"Unhandled file index: " <<
i
1219 << abort(FatalError);
1234 if (directForceDensity_)
1236 if (!obr_.foundObject<volVectorField>(fDName_))
1238 FatalErrorInFunction
1239 <<
"Could not find " << fDName_ <<
" in database."
1240 << exit(FatalError);
1247 !obr_.foundObject<volVectorField>(UName_)
1248 || !obr_.foundObject<volScalarField>(pName_)
1251 FatalErrorInFunction
1252 <<
"Could not find " << UName_ <<
", " << pName_
1253 << exit(FatalError);
1258 rhoName_ !=
"rhoInf"
1259 && !obr_.foundObject<volScalarField>(rhoName_)
1262 FatalErrorInFunction
1263 <<
"Could not find " << rhoName_
1264 << exit(FatalError);
1268 initialised_ =
true;
1272Foam::tmp<Foam::volSymmTensorField>
1275 typedef compressible::turbulenceModel cmpTurbModel;
1276 typedef incompressible::turbulenceModel icoTurbModel;
1278 if (obr_.foundObject<cmpTurbModel>(cmpTurbModel::propertiesName))
1280 const cmpTurbModel& turb =
1281 obr_.lookupObject<cmpTurbModel>(cmpTurbModel::propertiesName);
1282 return turb.devRhoReff();
1284 else if (obr_.foundObject<icoTurbModel>(icoTurbModel::propertiesName))
1286 const incompressible::turbulenceModel& turb =
1287 obr_.lookupObject<icoTurbModel>(icoTurbModel::propertiesName);
1288 return rho() * turb.devReff();
1290 else if (obr_.foundObject<fluidThermo>(fluidThermo::dictName))
1292 const fluidThermo& thermo =
1293 obr_.lookupObject<fluidThermo>(fluidThermo::dictName);
1294 const volVectorField&
U = obr_.lookupObject<volVectorField>(UName_);
1295 return -thermo.mu() * dev(twoSymm(fvc::grad(
U)));
1299 obr_.foundObject<transportModel>(
"transportProperties")
1302 const transportModel& laminarT =
1303 obr_.lookupObject<transportModel>(
"transportProperties");
1304 const volVectorField&
U = obr_.lookupObject<volVectorField>(UName_);
1305 return -rho() * laminarT.nu() * dev(twoSymm(fvc::grad(
U)));
1307 else if (obr_.foundObject<dictionary>(
"transportProperties"))
1310 obr_.lookupObject<dictionary>(
"transportProperties");
1312 const volVectorField&
U = obr_.lookupObject<volVectorField>(UName_);
1313 return -rho() *
nu * dev(twoSymm(fvc::grad(
U)));
1317 FatalErrorInFunction
1318 <<
"No valid model for viscous stress calculation"
1319 << exit(FatalError);
1320 return volSymmTensorField::null();
1327 if (obr_.foundObject<fluidThermo>(basicThermo::dictName))
1329 const fluidThermo& thermo =
1330 obr_.lookupObject<fluidThermo>(basicThermo::dictName);
1335 obr_.foundObject<transportModel>(
"transportProperties")
1338 const transportModel& laminarT =
1339 obr_.lookupObject<transportModel>(
"transportProperties");
1340 return rho() * laminarT.nu();
1342 else if (obr_.foundObject<dictionary>(
"transportProperties"))
1345 obr_.lookupObject<dictionary>(
"transportProperties");
1346 dimensionedScalar
nu
1356 FatalErrorInFunction
1357 <<
"No valid model for dynamic viscosity calculation"
1358 << exit(FatalError);
1359 return volScalarField::null();
1366 if (rhoName_ ==
"rhoInf")
1368 return tmp<volScalarField>
1375 mesh_.time().timeName(),
1379 dimensionedScalar(
"rho", dimDensity, rhoRef_)
1385 return (obr_.lookupObject<volScalarField>(rhoName_));
1393 if (
p.dimensions() == dimPressure)
1399 if (rhoName_ !=
"rhoInf")
1401 FatalErrorInFunction
1402 <<
"Dynamic pressure is expected but kinematic is provided."
1403 << exit(FatalError);
1413 const vectorField& Md,
1414 const vectorField& fN,
1415 const vectorField& fT,
1416 const vectorField& fP,
1417 const vectorField& d
1422 force_[0][0] += sum(fN);
1423 force_[1][0] += sum(fT);
1424 force_[2][0] += sum(fP);
1425 moment_[0][0] += sum(Md ^ fN);
1426 moment_[1][0] += sum(Md ^ fT);
1427 moment_[2][0] += sum(Md ^ fP);
1431 scalarField dd((d & binDir_) - binMin_);
1434 label bini = min(max(floor(dd[
i] / binDx_), 0), force_[0].size() - 1);
1435 force_[0][bini] += fN[
i];
1436 force_[1][bini] += fT[
i];
1437 force_[2][bini] += fP[
i];
1438 moment_[0][bini] += Md[
i] ^ fN[
i];
1439 moment_[1][bini] += Md[
i] ^ fT[
i];
1440 moment_[2][bini] += Md[
i] ^ fP[
i];
1448 Log << type() <<
" " << name() <<
" write:" << nl
1449 <<
" sum of forces:" << nl
1450 <<
" pressure : " << sum(force_[0]) << nl
1451 <<
" viscous : " << sum(force_[1]) << nl
1452 <<
" porous : " << sum(force_[2]) << nl
1453 <<
" sum of moments:" << nl
1454 <<
" pressure : " << sum(moment_[0]) << nl
1455 <<
" viscous : " << sum(moment_[1]) << nl
1456 <<
" porous : " << sum(moment_[2])
1458 writeTime(file(MAIN_FILE));
1459 file(MAIN_FILE) << tab << setw(1) <<
'('
1460 << sum(force_[0]) << setw(1) <<
' '
1461 << sum(force_[1]) << setw(1) <<
' '
1462 << sum(force_[2]) << setw(3) <<
") ("
1463 << sum(moment_[0]) << setw(1) <<
' '
1464 << sum(moment_[1]) << setw(1) <<
' '
1465 << sum(moment_[2]) << setw(1) <<
')'
1470 vectorField localForceN(coordSys_.localVector(force_[0]));
1471 vectorField localForceT(coordSys_.localVector(force_[1]));
1472 vectorField localForceP(coordSys_.localVector(force_[2]));
1473 vectorField localMomentN(coordSys_.localVector(moment_[0]));
1474 vectorField localMomentT(coordSys_.localVector(moment_[1]));
1475 vectorField localMomentP(coordSys_.localVector(moment_[2]));
1476 writeTime(file(MAIN_FILE));
1477 file(MAIN_FILE) << tab << setw(1) <<
'('
1478 << sum(localForceN) << setw(1) <<
' '
1479 << sum(localForceT) << setw(1) <<
' '
1480 << sum(localForceP) << setw(3) <<
") ("
1481 << sum(localMomentN) << setw(1) <<
' '
1482 << sum(localMomentT) << setw(1) <<
' '
1483 << sum(localMomentP) << setw(1) <<
')'
1496 List<Field<vector>> f(force_);
1497 List<Field<vector>> m(moment_);
1501 for (label
i = 1;
i < f[0].size();
i++)
1503 f[0][
i] += f[0][
i - 1];
1504 f[1][
i] += f[1][
i - 1];
1505 f[2][
i] += f[2][
i - 1];
1506 m[0][
i] += m[0][
i - 1];
1507 m[1][
i] += m[1][
i - 1];
1508 m[2][
i] += m[2][
i - 1];
1512 writeTime(file(BINS_FILE));
1516 << tab << setw(1) <<
'('
1517 << f[0][
i] << setw(1) <<
' '
1518 << f[1][
i] << setw(1) <<
' '
1519 << f[2][
i] << setw(3) <<
") ("
1520 << m[0][
i] << setw(1) <<
' '
1521 << m[1][
i] << setw(1) <<
' '
1522 << m[2][
i] << setw(1) <<
')';
1527 List<Field<vector>> lf(3);
1528 List<Field<vector>> lm(3);
1529 lf[0] = coordSys_.localVector(force_[0]);
1530 lf[1] = coordSys_.localVector(force_[1]);
1531 lf[2] = coordSys_.localVector(force_[2]);
1532 lm[0] = coordSys_.localVector(moment_[0]);
1533 lm[1] = coordSys_.localVector(moment_[1]);
1534 lm[2] = coordSys_.localVector(moment_[2]);
1538 for (label
i = 1;
i < lf[0].size();
i++)
1540 lf[0][
i] += lf[0][
i - 1];
1541 lf[1][
i] += lf[1][
i - 1];
1542 lf[2][
i] += lf[2][
i - 1];
1543 lm[0][
i] += lm[0][
i - 1];
1544 lm[1][
i] += lm[1][
i - 1];
1545 lm[2][
i] += lm[2][
i - 1];
1552 << tab << setw(1) <<
'('
1553 << lf[0][
i] << setw(1) <<
' '
1554 << lf[1][
i] << setw(1) <<
' '
1555 << lf[2][
i] << setw(3) <<
") ("
1556 << lm[0][
i] << setw(1) <<
' '
1557 << lm[1][
i] << setw(1) <<
' '
1558 << lm[2][
i] << setw(1) <<
')';
1562 file(BINS_FILE) << endl;
1572 const dictionary& dict
1575 fvMeshFunctionObject(name,
runTime, dict),
1576 logFiles(obr_, name),
1582 rhoName_(word::null),
1583 directForceDensity_(false),
1588 localSystem_(false),
1595 binCumulative_(true),
1606 const objectRegistry& obr,
1607 const dictionary& dict
1610 fvMeshFunctionObject(name, obr, dict),
1611 logFiles(obr_, name),
1617 rhoName_(word::null),
1618 directForceDensity_(false),
1623 localSystem_(false),
1630 binCumulative_(true),
1648 fvMeshFunctionObject::read(dict);
1649 initialised_ =
false;
1650 Log << type() <<
" " << name() <<
":" << nl;
1651 directForceDensity_ = dict.lookupOrDefault(
"directForceDensity",
false);
1652 const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
1653 patchSet_ = pbm.patchSet(wordReList(dict.lookup(
"patches")));
1655 if (directForceDensity_)
1658 fDName_ = dict.lookupOrDefault<word>(
"fD",
"fD");
1663 pName_ = dict.lookupOrDefault<word>(
"p",
"p");
1664 UName_ = dict.lookupOrDefault<word>(
"U",
"U");
1665 rhoName_ = dict.lookupOrDefault<word>(
"rho",
"rho");
1668 if (rhoName_ ==
"rhoInf")
1670 dict.lookup(
"rhoInf") >> rhoRef_;
1674 pRef_ = dict.lookupOrDefault<scalar>(
"pRef", 0.0);
1681 if (!dict.readIfPresent<point>(
"CofR", coordSys_.origin()))
1683 coordSys_ = coordinateSystem(obr_, dict);
1684 localSystem_ =
true;
1687 dict.readIfPresent(
"porosity", porosity_);
1691 Log <<
" Including porosity effects" << endl;
1695 Log <<
" Not including porosity effects" << endl;
1698 if (dict.found(
"binData"))
1700 const dictionary& binDict(dict.subDict(
"binData"));
1701 binDict.lookup(
"nBin") >> nBin_;
1705 FatalIOErrorInFunction(dict)
1706 <<
"Number of bins (nBin) must be zero or greater"
1707 << exit(FatalIOError);
1709 else if ((nBin_ == 0) || (nBin_ == 1))
1714 force_[
i].setSize(1);
1715 moment_[
i].setSize(1);
1721 binDict.lookup(
"direction") >> binDir_;
1722 binDir_ /= mag(binDir_);
1724 scalar binMax = -GREAT;
1725 forAllConstIter(labelHashSet, patchSet_, iter)
1727 label patchi = iter.key();
1728 const polyPatch& pp = pbm[patchi];
1729 scalarField d(pp.faceCentres() & binDir_);
1730 binMin_ = min(min(d), binMin_);
1731 binMax = max(max(d), binMax);
1733 reduce(binMin_, minOp<scalar>());
1734 reduce(binMax, maxOp<scalar>());
1737 binMax = 1.0001 * (binMax - binMin_) + binMin_;
1738 binDx_ = (binMax - binMin_) / scalar(nBin_);
1740 binPoints_.setSize(nBin_);
1743 binPoints_[
i] = (
i + 0.5) * binDir_ * binDx_;
1745 binDict.lookup(
"cumulative") >> binCumulative_;
1749 force_[
i].setSize(nBin_);
1750 moment_[
i].setSize(nBin_);
1758 force_[0].setSize(1);
1759 force_[1].setSize(1);
1760 force_[2].setSize(1);
1761 moment_[0].setSize(1);
1762 moment_[1].setSize(1);
1763 moment_[2].setSize(1);
1780 if (directForceDensity_)
1782 const volVectorField& fD = obr_.lookupObject<volVectorField>(fDName_);
1783 const surfaceVectorField::Boundary& Sfb =
1784 mesh_.Sf().boundaryField();
1785 forAllConstIter(labelHashSet, patchSet_, iter)
1787 label patchi = iter.key();
1790 mesh_.C().boundaryField()[patchi] - coordSys_.origin()
1792 scalarField sA(mag(Sfb[patchi]));
1798 Sfb[patchi] & fD.boundaryField()[patchi]
1802 vectorField fT(sA * fD.boundaryField()[patchi] - fN);
1804 vectorField fP(Md.size(), Zero);
1805 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[patchi]);
1810 const volScalarField&
p = obr_.lookupObject<volScalarField>(pName_);
1811 const surfaceVectorField::Boundary& Sfb =
1812 mesh_.Sf().boundaryField();
1813 tmp<volSymmTensorField> tdevRhoReff = devRhoReff();
1814 const volSymmTensorField::Boundary& devRhoReffb
1815 = tdevRhoReff().boundaryField();
1817 scalar pRef = pRef_ / rho(
p);
1818 forAllConstIter(labelHashSet, patchSet_, iter)
1820 label patchi = iter.key();
1823 mesh_.C().boundaryField()[patchi] - coordSys_.origin()
1827 rho(
p)*Sfb[patchi] * (
p.boundaryField()[patchi] - pRef)
1829 vectorField fT(Sfb[patchi] & devRhoReffb[patchi]);
1830 vectorField fP(Md.size(), Zero);
1831 applyBins(Md, fN, fT, fP, mesh_.C().boundaryField()[patchi]);
1837 const volVectorField&
U = obr_.lookupObject<volVectorField>(UName_);
1838 const volScalarField rho(this->rho());
1839 const volScalarField mu(this->mu());
1840 const HashTable<const porosityModel*> models =
1841 obr_.lookupClass<porosityModel>();
1846 <<
"Porosity effects requested, but no porosity models found "
1847 <<
"in the database"
1851 forAllConstIter(HashTable<const porosityModel*>, models, iter)
1854 porosityModel& pm =
const_cast<porosityModel&
>(*iter());
1855 vectorField fPTot(pm.force(
U, rho, mu));
1856 const labelList& cellZoneIDs = pm.cellZoneIDs();
1859 label zoneI = cellZoneIDs[
i];
1860 const cellZone& cZone = mesh_.cellZones()[zoneI];
1861 const vectorField d(mesh_.C(), cZone);
1862 const vectorField fP(fPTot, cZone);
1863 const vectorField Md(d - coordSys_.origin());
1864 const vectorField fDummy(Md.size(), Zero);
1865 applyBins(Md, fDummy, fDummy, fP, d);
1870 Pstream::listCombineGather(force_, plusEqOp<vectorField>());
1871 Pstream::listCombineGather(moment_, plusEqOp<vectorField>());
1872 Pstream::listCombineScatter(force_);
1873 Pstream::listCombineScatter(moment_);
1879 return sum(force_[0]) + sum(force_[1]) + sum(force_[2]);
1885 return sum(moment_[0]) + sum(moment_[1]) + sum(moment_[2]);
1896 return sum(force_[2]);
1901 return sum(force_[0]);
1906 return sum(force_[1]);
1914 if (Pstream::master())
forAll(example_CG.gList, solutionI)
virtual vector forcePressure() const
virtual vector forceEff() const
void writeBinnedForceMoment(const List< Field< vector > > &fm, autoPtr< OFstream > &osPtr) const
void writeIntegratedForceMoment(const string &descriptor, const vectorField &fm0, const vectorField &fm1, const vectorField &fm2, autoPtr< OFstream > &osPtr) const
virtual bool read(const dictionary &)
virtual void writeFileHeader(const label i)
virtual vector forcePorous() const
tmp< volScalarField > rho() const
tmp< volScalarField > mu() const
void applyBins(const vectorField &Md, const vectorField &fN, const vectorField &fT, const vectorField &fP, const vectorField &d)
wordList createFileNames(const dictionary &dict) const
void addToFields(const label patchi, const vectorField &Md, const vectorField &fN, const vectorField &fT, const vectorField &fP)
virtual vector forceTau() const
word fieldName(const word &name) const
virtual vector momentEff() const
void writeBinHeader(const word &header, Ostream &os) const
virtual void calcForcesMoment()
void writeIntegratedHeader(const word &header, Ostream &os) const
tmp< volSymmTensorField > devRhoReff() const
ITHACAforces(const ITHACAforces &)
T max(Eigen::SparseMatrix< T > &mat, label &ind_row, label &ind_col)
Find the maximum of a sparse Matrix (Useful for DEIM)
T min(Eigen::SparseMatrix< T > &mat, label &ind_row, label &ind_col)
Find the minimum of a sparse Matrix (Useful for DEIM)
defineTypeNameAndDebug(ITHACAforces, 0)
addToRunTimeSelectionTable(functionObject, ITHACAforces, dictionary)
IOdictionary transportProperties(IOobject("transportProperties", runTime.constant(), mesh, IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE))