37 Foam::turbulentDigitalFilterInletFvPatchVectorField::variantType
39 Foam::turbulentDigitalFilterInletFvPatchVectorField::variantNames
41 { variantType::DIGITAL_FILTER,
"digitalFilter" },
42 { variantType::DIGITAL_FILTER,
"DFM" },
43 { variantType::FORWARD_STEPWISE,
"forwardStepwise" },
44 { variantType::FORWARD_STEPWISE,
"reducedDigitalFilter" },
45 { variantType::FORWARD_STEPWISE,
"FSM" }
51 Foam::turbulentDigitalFilterInletFvPatchVectorField::patchMapper()
const
54 if (mapperPtr_.empty())
57 fileName samplePointsFile
59 this->db().time().
path()
60 /this->db().time().caseConstant()
66 pointField samplePoints((IFstream(samplePointsFile)()));
72 && mapMethod_ !=
"planarInterpolation"
78 new pointToPointPlanarInterpolation
93 Foam::turbulentDigitalFilterInletFvPatchVectorField::patchIndexPairs()
96 const vector nf(computePatchNormal());
100 scalar minMag = VGREAT;
101 for (
direction cmpt = 0; cmpt < pTraits<vector>::nComponents; ++cmpt)
103 scalar
s =
mag(nf[cmpt]);
119 coordSystem::cartesian cs
139 const boundBox bb(localPos);
142 const Vector2D<label>
n(planeDivisions_.first(), planeDivisions_.second());
143 invDelta_[0] =
n[0]/bb.span()[0];
144 invDelta_[1] =
n[1]/bb.span()[1];
145 const point localMinPt(bb.min());
148 List<Pair<label>> indexPairs(this->size(), Pair<label>(
Zero,
Zero));
156 const scalar& centre0 = localPos[facei][0];
157 const scalar& centre1 = localPos[facei][1];
159 j =
label((centre0 - localMinPt[0])*invDelta_[0]);
160 k =
label((centre1 - localMinPt[1])*invDelta_[1]);
162 indexPairs[facei] = Pair<label>(facei,
k*
n[0] + j);
169 void Foam::turbulentDigitalFilterInletFvPatchVectorField::
170 checkRTensorRealisable()
const
176 if (R_[facei].xx() <= 0)
179 <<
"Reynolds stress tensor component Rxx cannot be negative"
180 "or zero, where Rxx = " << R_[facei].xx() <<
" at the face "
184 if (R_[facei].yy() < 0 || R_[facei].zz() < 0)
187 <<
"Reynolds stress tensor components Ryy or Rzz cannot be"
188 <<
"negative where Ryy = " << R_[facei].yy() <<
", and Rzz = "
189 << R_[facei].zz() <<
" at the face centre = "
193 scalar term0 = R_[facei].xx()*R_[facei].yy() -
sqr(R_[facei].xy());
198 <<
"Reynolds stress tensor component group, Rxx*Ryy - Rxy^2"
199 <<
"cannot be negative or zero at the face centre = "
203 scalar term1 = R_[facei].zz() -
sqr(R_[facei].xz())/R_[facei].xx();
205 sqr(R_[facei].yz() - R_[facei].xy()*R_[facei].xz()
206 /(R_[facei].xx()*term0));
207 scalar term3 = term1 - term2;
212 <<
"Reynolds stress tensor component group,"
213 <<
"Rzz - Rxz^2/Rxx - (Ryz - Rxy*Rxz/(Rxx*(Rxx*Ryy - Rxy^2)))^2"
214 <<
"cannot be negative at the face centre = "
220 Info<<
"Ends: checkRTensorRealisable()."
221 <<
" Reynolds tensor (on patch) is consistent." <<
nl;
227 computeLundWuSquires()
const
229 checkRTensorRealisable();
240 lws.xy() =
R.xy()/lws.xx();
241 lws.xz() =
R.xz()/lws.xx();
243 lws.yz() = (
R.yz() - lws.xy()*lws.xz())/lws.yy();
248 Info<<
"Ends: computeLundWuSquires()." <<
nl;
251 return LundWuSquires;
255 Foam::vector Foam::turbulentDigitalFilterInletFvPatchVectorField::
256 computePatchNormal()
const
259 return patchNormal.normalise();
263 Foam::scalar Foam::turbulentDigitalFilterInletFvPatchVectorField::
264 computeInitialFlowRate()
const
266 const vector patchNormal(computePatchNormal());
267 return gSum((UMean_ & patchNormal)*
patch().magSf());
271 void Foam::turbulentDigitalFilterInletFvPatchVectorField::convertToTimeScale
280 L[i] /= patchNormalSpeed_;
284 Info<<
"Ends: convertToTimeScale()."
285 <<
"Streamwise integral length scales are converted to time scales via"
286 <<
"Taylor's frozen turbulence hypothesis" <<
nl;
292 Foam::tensor Foam::turbulentDigitalFilterInletFvPatchVectorField::
293 convertScalesToGridUnits
299 convertToTimeScale(Ls);
300 const scalar invDeltaT = 1.0/db().time().deltaTValue();
302 Ls.row(0, Ls.x()*invDeltaT);
303 Ls.row(1, Ls.y()*invDelta_[0]);
304 Ls.row(2, Ls.z()*invDelta_[1]);
307 Info<<
"Ends: convertScalesToGridUnits()."
308 <<
"Units of input length scales are converted from metres to"
309 <<
"virtual-patch cell size/time-step" <<
nl;
317 initLenRandomBox()
const
320 label rangeModifier = 0;
322 if (variant_ == variantType::FORWARD_STEPWISE)
325 initValue = pTraits<label>::nComponents;
326 rangeModifier = pTraits<vector>::nComponents;
329 List<label> lenRandomBox(pTraits<tensor>::nComponents, initValue);
330 Vector<label> lenGrid
332 pTraits<label>::nComponents,
333 planeDivisions_.first(),
334 planeDivisions_.second()
341 : labelRange(rangeModifier, pTraits<tensor>::nComponents - rangeModifier)
345 const label sliceI =
label(i/pTraits<vector>::nComponents);
348 const label n = ceil(L_[i]);
352 lenRandomBox[i] = lenGrid[sliceI] + twiceN;
360 initBoxFactors2D()
const
362 List<label> boxFactors2D(pTraits<vector>::nComponents);
364 for (
direction dir = 0; dir < pTraits<vector>::nComponents; ++dir)
367 lenRandomBox_[pTraits<vector>::nComponents + dir]
368 *lenRandomBox_[pTraits<symmTensor>::nComponents + dir];
376 initBoxFactors3D()
const
378 List<label> boxFactors3D(pTraits<vector>::nComponents);
380 for (
direction dir = 0; dir < pTraits<vector>::nComponents; ++dir)
382 boxFactors3D[dir] = randomBoxFactors2D_[dir]*lenRandomBox_[dir];
390 initBoxPlaneFactors()
const
392 List<label> planeFactors(pTraits<vector>::nComponents);
394 for (
direction dir = 0; dir < pTraits<vector>::nComponents; ++dir)
397 randomBoxFactors2D_[dir]*(lenRandomBox_[dir] - pTraits<label>::one);
405 Foam::turbulentDigitalFilterInletFvPatchVectorField::fillRandomBox()
407 List<List<scalar>> randomBox(pTraits<vector>::nComponents, List<scalar>());
410 for (
direction dir = 0; dir < pTraits<vector>::nComponents; ++dir)
414 generateRandomSet<List<scalar>, scalar>(randomBoxFactors3D_[dir]);
418 Info<<
"Ends: fillRandomBox()."
419 <<
"Random-number box is created." <<
nl;
427 Foam::turbulentDigitalFilterInletFvPatchVectorField::computeFilterCoeffs()
const
429 List<List<scalar>> filterCoeffs
431 pTraits<tensor>::nComponents,
437 if(variant_ == variantType::FORWARD_STEPWISE)
439 initValue = pTraits<vector>::nComponents;
442 for (
direction dir = initValue; dir < pTraits<tensor>::nComponents; ++dir)
446 const label n = ceil(L_[dir]);
454 filterCoeffs[dir] = List<scalar>(twiceN + 1,
Zero);
457 const scalar initElem = -2*scalar(
n);
463 filterCoeffs[dir].
begin(),
464 filterCoeffs[dir].
end(),
471 List<scalar> fTemp(filterCoeffs[dir]);
473 const scalar nSqr =
n*
n;
477 fTemp =
sqr(
exp(modelConst_*
sqr(fTemp)/nSqr));
481 exp(modelConst_*
sqr(filterCoeffs[dir])/nSqr)/fSum;
488 filterCoeffs[dir] =
exp(modelConst_*
mag(filterCoeffs[dir])/
n)/fSum;
493 Info<<
"Ends: computeFilterCoeffs()."
494 <<
" Filter coefficients are computed." <<
nl;
501 void Foam::turbulentDigitalFilterInletFvPatchVectorField::rndShiftRefill()
505 List<scalar>& r = randomBox_[dir];
511 for (
label i = 0; i < randomBoxFactors2D_[dir]; ++i)
513 r[i] = rndGen_.GaussNormal<scalar>();
519 void Foam::turbulentDigitalFilterInletFvPatchVectorField::mapFilteredRandomBox
524 for (
const auto&
x : indexPairs_)
526 const label xf =
x.first();
527 const label xs =
x.second();
528 U[xf][0] = filteredRandomBox_[0][xs];
529 U[xf][1] = filteredRandomBox_[1][xs];
530 U[xf][2] = filteredRandomBox_[2][xs];
535 void Foam::turbulentDigitalFilterInletFvPatchVectorField::embedOnePointCorrs
540 forAll(LundWuSquires_, facei)
543 const symmTensor& lws = LundWuSquires_[facei];
546 Us.z() =
Us.x()*lws.xz() +
Us.y()*lws.yz() +
Us.z()*lws.zz();
547 Us.y() =
Us.x()*lws.xy() +
Us.y()*lws.yy();
548 Us.x() =
Us.x()*lws.xx();
553 void Foam::turbulentDigitalFilterInletFvPatchVectorField::embedMeanVelocity
562 void Foam::turbulentDigitalFilterInletFvPatchVectorField::correctFlowRate
571 void Foam::turbulentDigitalFilterInletFvPatchVectorField::embedTwoPointCorrs()
573 for (
direction dir = 0; dir < pTraits<vector>::nComponents; ++dir)
575 List<scalar>& in = randomBox_[dir];
576 List<scalar>& out = filteredRandomBox_[dir];
577 const List<scalar>& filter1 = filterCoeffs_[dir];
578 const List<scalar>& filter2 = filterCoeffs_[3 + dir];
579 const List<scalar>& filter3 = filterCoeffs_[6 + dir];
581 const label sz1 = lenRandomBox_[dir];
582 const label sz2 = lenRandomBox_[3 + dir];
583 const label sz3 = lenRandomBox_[6 + dir];
584 const label szfilter1 = filterCoeffs_[dir].size();
585 const label szfilter2 = filterCoeffs_[3 + dir].size();
586 const label szfilter3 = filterCoeffs_[6 + dir].size();
587 const label sz23 = randomBoxFactors2D_[dir];
588 const label sz123 = randomBoxFactors3D_[dir];
589 const label validSlice2 = sz2 - (szfilter2 -
label(1));
590 const label validSlice3 = sz3 - (szfilter3 -
label(1));
595 label endIndex = sz2 - filterCentre;
600 for (
label i = 0; i < sz1; ++i)
602 for (
label j = 0; j < sz3; ++j)
606 for (
label k = filterCentre;
k < endIndex; ++
k)
611 for (
label p = szfilter2 - 1;
p >= 0; --
p, ++q)
613 tmp[i1] += in[i0 + q]*filter2[
p];
619 i0 += (filterCentre + filterCentre);
627 endIndex = sz3 - filterCentre;
631 for (
label i = 0; i < sz1; ++i)
635 for (
label j = 0; j < sz2; ++j)
640 for (
label k = 0;
k < endIndex - filterCentre; ++
k)
645 for (
label p = szfilter3 - 1;
p >= 0; --
p, ++q)
647 tmp[i1] += tmp2[i2 + q*sz2]*filter3[
p];
653 i1 += (sz2 + filterCentre);
654 i2 += (sz2 + filterCentre);
660 endIndex = sz1 - filterCentre;
665 for (
label i = 0; i < validSlice3; ++i)
667 for (
label j = 0; j < validSlice2; ++j)
672 for (
label k = szfilter1 - 1;
k >= 0; --
k)
674 sum += tmp[i1]*filter1[
k];
687 void Foam::turbulentDigitalFilterInletFvPatchVectorField::computeDFM
693 Info<<
"Starts: computeDFM()" <<
nl;
698 embedTwoPointCorrs();
704 mapFilteredRandomBox(
U);
706 embedOnePointCorrs(
U);
708 embedMeanVelocity(
U);
710 if (isCorrectedFlowRate_)
716 Info<<
"Ends: computeDFM()" <<
nl;
721 void Foam::turbulentDigitalFilterInletFvPatchVectorField::computeReducedDFM
727 Info<<
"Starts: computeReducedDFM()" <<
nl;
732 embedTwoPointCorrs();
738 mapFilteredRandomBox(
U);
742 embedOnePointCorrs(
U);
744 embedMeanVelocity(
U);
746 if (isCorrectedFlowRate_)
752 Info<<
"Ends: computeReducedDFM()" <<
nl;
758 computeConstList1FSM()
const
760 List<scalar> constList1FSM(pTraits<vector>::nComponents);
764 constList1FSM[i] =
exp(const1FSM_/L_[i]);
767 return constList1FSM;
772 computeConstList2FSM()
const
774 List<scalar> constList2FSM(pTraits<vector>::nComponents);
781 return constList2FSM;
785 void Foam::turbulentDigitalFilterInletFvPatchVectorField::computeFSM
790 for (
direction dir = 0; dir < pTraits<vector>::nComponents; ++dir)
792 U.component(dir) = U0_.component(dir)*constList1FSM_[dir]
793 +
U.component(dir)*constList2FSM_[dir];
811 variant_(variantType::DIGITAL_FILTER),
814 isContinuous_(
false),
815 isCorrectedFlowRate_(
true),
816 interpolateR_(
false),
817 interpolateUMean_(
false),
818 isInsideMesh_(
false),
819 isTaylorHypot_(
true),
820 mapMethod_(
"nearestCell"),
823 patchNormalSpeed_(
Zero),
832 LundWuSquires_(
Zero),
838 constList1FSM_(
Zero),
839 constList2FSM_(
Zero),
841 randomBoxFactors2D_(
Zero),
842 randomBoxFactors3D_(
Zero),
843 iNextToLastPlane_(
Zero),
846 filteredRandomBox_(
Zero),
848 computeVariant(
nullptr)
863 variant_(ptf.variant_),
864 isGaussian_(ptf.isGaussian_),
865 isFixedSeed_(ptf.isFixedSeed_),
866 isContinuous_(ptf.isContinuous_),
867 isCorrectedFlowRate_(ptf.isCorrectedFlowRate_),
868 interpolateR_(ptf.interpolateR_),
869 interpolateUMean_(ptf.interpolateUMean_),
870 isInsideMesh_(ptf.isInsideMesh_),
871 isTaylorHypot_(ptf.isTaylorHypot_),
872 mapMethod_(ptf.mapMethod_),
875 patchNormalSpeed_(ptf.patchNormalSpeed_),
876 modelConst_(ptf.modelConst_),
877 perturb_(ptf.perturb_),
878 initialFlowRate_(ptf.initialFlowRate_),
879 rndGen_(ptf.rndGen_),
880 planeDivisions_(ptf.planeDivisions_),
881 invDelta_(ptf.invDelta_),
882 indexPairs_(ptf.indexPairs_),
884 LundWuSquires_(ptf.LundWuSquires_),
888 const1FSM_(ptf.const1FSM_),
889 const2FSM_(ptf.const2FSM_),
890 constList1FSM_(ptf.constList1FSM_),
891 constList2FSM_(ptf.constList2FSM_),
892 lenRandomBox_(ptf.lenRandomBox_),
893 randomBoxFactors2D_(ptf.randomBoxFactors2D_),
894 randomBoxFactors3D_(ptf.randomBoxFactors3D_),
895 iNextToLastPlane_(ptf.iNextToLastPlane_),
896 randomBox_(ptf.randomBox_),
897 filterCoeffs_(ptf.filterCoeffs_),
898 filteredRandomBox_(ptf.filteredRandomBox_),
900 computeVariant(ptf.computeVariant)
916 variantNames.getOrDefault
920 variantType::DIGITAL_FILTER
925 (variant_ == variantType::FORWARD_STEPWISE)
970 return tiny_ < min(len.first(), len.second()) ? true : false;
975 indexPairs_(patchIndexPairs()),
976 R_(interpolateOrRead<symmTensor>(
"R",
dict, interpolateR_)),
977 LundWuSquires_(computeLundWuSquires()),
978 UMean_(interpolateOrRead<vector>(
"UMean",
dict, interpolateUMean_)),
984 [&](
const tensor& l){return tiny_ < cmptMin(l) ? true : false;}
987 L_(convertScalesToGridUnits(Lbak_)),
990 (variant_ == variantType::FORWARD_STEPWISE)
1000 (variant_ == variantType::FORWARD_STEPWISE)
1010 (variant_ == variantType::FORWARD_STEPWISE)
1011 ? computeConstList1FSM()
1016 (variant_ == variantType::FORWARD_STEPWISE)
1017 ? computeConstList2FSM()
1020 lenRandomBox_(initLenRandomBox()),
1021 randomBoxFactors2D_(initBoxFactors2D()),
1022 randomBoxFactors3D_(initBoxFactors3D()),
1023 iNextToLastPlane_(initBoxPlaneFactors()),
1035 filterCoeffs_(computeFilterCoeffs()),
1043 (variant_ == variantType::FORWARD_STEPWISE)
1044 ? generateRandomSet<vectorField, vector>(
patch().size())
1049 (variant_ == variantType::FORWARD_STEPWISE)
1050 ? &turbulentDigitalFilterInletFvPatchVectorField::computeReducedDFM
1051 : &turbulentDigitalFilterInletFvPatchVectorField::computeDFM
1054 if (isCorrectedFlowRate_)
1056 initialFlowRate_ = computeInitialFlowRate();
1060 if (db().time().isAdjustTimeStep())
1063 <<
"Varying time-step computations are not fully supported"
1064 <<
" for the moment."<<
nl <<
nl;
1068 Info<<
"Ends: Resource acquisition/initialisation for the"
1069 <<
" synthetic turbulence boundary condition." <<
nl;
1081 mapperPtr_(
nullptr),
1082 variant_(ptf.variant_),
1083 isGaussian_(ptf.isGaussian_),
1084 isFixedSeed_(ptf.isFixedSeed_),
1085 isContinuous_(ptf.isContinuous_),
1086 isCorrectedFlowRate_(ptf.isCorrectedFlowRate_),
1087 interpolateR_(ptf.interpolateR_),
1088 interpolateUMean_(ptf.interpolateUMean_),
1089 isInsideMesh_(ptf.isInsideMesh_),
1090 isTaylorHypot_(ptf.isTaylorHypot_),
1091 mapMethod_(ptf.mapMethod_),
1092 curTimeIndex_(ptf.curTimeIndex_),
1094 patchNormalSpeed_(ptf.patchNormalSpeed_),
1095 modelConst_(ptf.modelConst_),
1096 perturb_(ptf.perturb_),
1097 initialFlowRate_(ptf.initialFlowRate_),
1098 rndGen_(ptf.rndGen_),
1099 planeDivisions_(ptf.planeDivisions_),
1100 invDelta_(ptf.invDelta_),
1101 indexPairs_(ptf.indexPairs_),
1103 LundWuSquires_(ptf.LundWuSquires_),
1107 const1FSM_(ptf.const1FSM_),
1108 const2FSM_(ptf.const2FSM_),
1109 constList1FSM_(ptf.constList1FSM_),
1110 constList2FSM_(ptf.constList2FSM_),
1111 lenRandomBox_(ptf.lenRandomBox_),
1112 randomBoxFactors2D_(ptf.randomBoxFactors2D_),
1113 randomBoxFactors3D_(ptf.randomBoxFactors3D_),
1114 iNextToLastPlane_(ptf.iNextToLastPlane_),
1115 randomBox_(ptf.randomBox_),
1116 filterCoeffs_(ptf.filterCoeffs_),
1117 filteredRandomBox_(ptf.filteredRandomBox_),
1119 computeVariant(ptf.computeVariant)
1131 mapperPtr_(
nullptr),
1132 variant_(ptf.variant_),
1133 isGaussian_(ptf.isGaussian_),
1134 isFixedSeed_(ptf.isFixedSeed_),
1135 isContinuous_(ptf.isContinuous_),
1136 isCorrectedFlowRate_(ptf.isCorrectedFlowRate_),
1137 interpolateR_(ptf.interpolateR_),
1138 interpolateUMean_(ptf.interpolateUMean_),
1139 isInsideMesh_(ptf.isInsideMesh_),
1140 isTaylorHypot_(ptf.isTaylorHypot_),
1141 mapMethod_(ptf.mapMethod_),
1144 patchNormalSpeed_(ptf.patchNormalSpeed_),
1145 modelConst_(ptf.modelConst_),
1146 perturb_(ptf.perturb_),
1147 initialFlowRate_(ptf.initialFlowRate_),
1148 rndGen_(ptf.rndGen_),
1149 planeDivisions_(ptf.planeDivisions_),
1150 invDelta_(ptf.invDelta_),
1151 indexPairs_(ptf.indexPairs_),
1153 LundWuSquires_(ptf.LundWuSquires_),
1157 const1FSM_(ptf.const1FSM_),
1158 const2FSM_(ptf.const2FSM_),
1159 constList1FSM_(ptf.constList1FSM_),
1160 constList2FSM_(ptf.constList2FSM_),
1161 lenRandomBox_(ptf.lenRandomBox_),
1162 randomBoxFactors2D_(ptf.randomBoxFactors2D_),
1163 randomBoxFactors3D_(ptf.randomBoxFactors3D_),
1164 iNextToLastPlane_(ptf.iNextToLastPlane_),
1165 randomBox_(ptf.randomBox_),
1166 filterCoeffs_(ptf.filterCoeffs_),
1167 filteredRandomBox_(ptf.filteredRandomBox_),
1169 computeVariant(ptf.computeVariant)
1182 if (curTimeIndex_ != db().time().
timeIndex())
1186 computeVariant(
this,
U);
1188 curTimeIndex_ = db().time().timeIndex();
1191 fixedValueFvPatchVectorField::updateCoeffs();
1201 os.
writeEntry(
"variant", variantNames[variant_]);
1202 os.
writeEntry(
"planeDivisions", planeDivisions_);
1210 if (!interpolateUMean_)
1219 (
"isCorrectedFlowRate",
true, isCorrectedFlowRate_);
1223 if (!mapMethod_.empty())
1234 os.
writeEntry(
"patchNormalSpeed", patchNormalSpeed_);
1238 if (variant_ == variantType::FORWARD_STEPWISE)