36 Foam::label Foam::turbulentDFSEMInletFvPatchVectorField::seedIterMax_ = 1000;
40 void Foam::turbulentDFSEMInletFvPatchVectorField::writeEddyOBJ()
const
44 OFstream
os(db().time().
path()/
"eddyBox.obj");
46 const polyPatch& pp = this->
patch().patch();
47 const labelList& boundaryPoints = pp.boundaryPoints();
48 const pointField& localPoints = pp.localPoints();
50 const vector offset(patchNormal_*maxSigmaX_);
53 point p = localPoints[boundaryPoints[i]];
55 os <<
"v " <<
p.x() <<
" " <<
p.y() <<
" " <<
p.z() <<
nl;
60 point p = localPoints[boundaryPoints[i]];
62 os <<
"v " <<
p.x() <<
" " <<
p.y() <<
" " <<
p.z() <<
nl;
67 const Time& time = db().time();
70 time.path()/
"eddies_" +
Foam::name(time.timeIndex()) +
".obj"
73 label pointOffset = 0;
76 const eddy&
e = eddies_[eddyI];
77 pointOffset +=
e.writeSurfaceOBJ(pointOffset, patchNormal_,
os);
83 void Foam::turbulentDFSEMInletFvPatchVectorField::writeLumleyCoeffs()
const
87 OFstream
os(db().time().
path()/
"lumley_interpolated.out");
91 const scalar t = db().time().timeOutputValue();
107 const scalar xi =
cbrt(0.5*iii);
108 const scalar eta =
sqrt(-ii/3.0);
115 void Foam::turbulentDFSEMInletFvPatchVectorField::initialisePatch()
123 const scalar error =
max(
magSqr(patchNormal_ + nf));
128 <<
"Patch " <<
patch().name() <<
" is not planar"
132 patchNormal_ /=
mag(patchNormal_) + ROOTVSMALL;
137 const polyPatch&
patch = this->
patch().patch();
141 DynamicList<label> triToFace(2*
patch.size());
142 DynamicList<scalar> triMagSf(2*
patch.size());
144 DynamicList<face> tris(5);
147 triMagSf.append(0.0);
151 const face&
f =
patch[faceI];
158 triToFace.append(faceI);
164 for (
auto&
s : sumTriMagSf_)
174 for (label i = 1; i < triMagSf.size(); ++i)
176 triMagSf[i] += triMagSf[i-1];
181 triToFace_.transfer(triToFace);
182 triCumulativeMagSf_.transfer(triMagSf);
185 for (label i = 1; i < sumTriMagSf_.size(); ++i)
187 sumTriMagSf_[i] += sumTriMagSf_[i-1];
191 patchArea_ = sumTriMagSf_.last();
194 patchBounds_ = boundBox(
patch.localPoints(),
false);
195 patchBounds_.inflate(0.1);
199 reduce(singleProc_, orOp<bool>());
203 void Foam::turbulentDFSEMInletFvPatchVectorField::initialiseEddyBox()
207 const scalarField L(L_->value(db().time().timeOutputValue())/Lref_);
215 scalar&
s = sigmax_[faceI];
220 s =
min(
mag(
L[faceI]), kappa_*delta_);
221 s =
max(
s, nCellPerEddy_*cellDx[faceI]);
225 maxSigmaX_ =
gMax(sigmax_);
228 v0_ = 2*
gSum(magSf)*maxSigmaX_;
232 Info<<
"Patch: " <<
patch().patch().name() <<
" eddy box:" <<
nl
233 <<
" volume : " << v0_ <<
nl
234 <<
" maxSigmaX : " << maxSigmaX_ <<
nl
248 const polyPatch&
patch = this->
patch().patch();
253 const scalar areaFraction =
254 rndGen_.globalPosition<scalar>(0, patchArea_);
260 if (areaFraction >= sumTriMagSf_[i])
271 const scalar offset = sumTriMagSf_[procI];
274 if (areaFraction > triCumulativeMagSf_[i] + offset)
282 const face& tf = triFace_[triI];
286 pos.setIndex(triToFace_[triI]);
287 pos.rawPoint() = tri.randomPoint(rndGen_);
294 const scalar maxAreaLimit = triCumulativeMagSf_.last();
295 const scalar areaFraction = rndGen_.position<scalar>(0, maxAreaLimit);
299 if (areaFraction > triCumulativeMagSf_[i])
307 const face& tf = triFace_[triI];
311 pos.setIndex(triToFace_[triI]);
312 pos.rawPoint() = tri.randomPoint(rndGen_);
319 void Foam::turbulentDFSEMInletFvPatchVectorField::initialiseEddies()
321 const scalar t = db().time().timeOutputValue();
324 DynamicList<eddy> eddies(size());
327 scalar sumVolEddy = 0;
328 scalar sumVolEddyAllProc = 0;
330 while (sumVolEddyAllProc/v0_ < d_)
335 while (
search && iter++ < seedIterMax_)
339 const label patchFaceI =
pos.index();
342 if (patchFaceI != -1)
348 rndGen_.position<scalar>(-maxSigmaX_, maxSigmaX_),
355 if (
e.patchFaceI() != -1)
358 sumVolEddy +=
e.volume();
368 sumVolEddyAllProc =
returnReduce(sumVolEddy, sumOp<scalar>());
370 eddies_.transfer(eddies);
372 nEddy_ = eddies_.size();
376 Pout<<
"Patch:" <<
patch().patch().name();
383 Pout<<
" seeded:" << nEddy_ <<
" eddies" <<
endl;
386 reduce(nEddy_, sumOp<label>());
390 Info<<
"Turbulent DFSEM patch: " <<
patch().name()
391 <<
" seeded " << nEddy_ <<
" eddies with total volume "
398 <<
"Patch: " <<
patch().patch().name()
399 <<
" on field " << internalField().name()
400 <<
": No eddies seeded - please check your set-up"
406 void Foam::turbulentDFSEMInletFvPatchVectorField::convectEddies
412 const scalar t = db().time().timeOutputValue();
421 eddy&
e = eddies_[eddyI];
422 e.move(deltaT*(UBulk & patchNormal_));
424 const scalar position0 =
e.x();
427 if (position0 > maxSigmaX_)
432 while (
search && iter++ < seedIterMax_)
436 const label patchFaceI =
pos.index();
442 position0 - floor(position0/maxSigmaX_)*maxSigmaX_,
448 if (
e.patchFaceI() != -1)
458 reduce(nRecycled, sumOp<label>());
460 if (
debug && nRecycled > 0)
462 Info<<
"Patch: " <<
patch().patch().name()
463 <<
" recycled " << nRecycled <<
" eddies"
469 Foam::vector Foam::turbulentDFSEMInletFvPatchVectorField::uPrimeEddy
471 const List<eddy>& eddies,
472 const point& patchFaceCf
479 const eddy&
e = eddies[
k];
480 uPrime +=
e.uPrime(patchFaceCf, patchNormal_);
487 void Foam::turbulentDFSEMInletFvPatchVectorField::calcOverlappingProcEddies
489 List<List<eddy>>& overlappingEddies
506 const eddy&
e = eddies_[i];
509 const point x(
e.position(patchNormal_));
510 boundBox ebb(
e.bounds());
519 if (ebb.overlaps(patchBBs[procI]))
521 dynSendMap[procI].append(i);
530 sendMap[procI].transfer(dynSendMap[procI]);
553 forAll(constructMap, procI)
559 constructMap[procI].setSize(nRecv);
561 for (label i = 0; i < nRecv; ++i)
563 constructMap[procI][i] = segmentI++;
568 mapDistribute map(segmentI, std::move(sendMap), std::move(constructMap));
574 const labelList& sendElems = map.subMap()[domain];
578 List<eddy> subEddies(UIndirectList<eddy>(eddies_, sendElems));
580 UOPstream toDomain(domain, pBufs);
582 toDomain<< subEddies;
587 pBufs.finishedSends();
592 const labelList& recvElems = map.constructMap()[domain];
596 UIPstream str(domain, pBufs);
598 str >> overlappingEddies[domain];
633 triCumulativeMagSf_(),
636 patchBounds_(
boundBox::invertedBox),
641 sigmax_(size(),
Zero),
670 nCellPerEddy_(ptf.nCellPerEddy_),
672 patchArea_(ptf.patchArea_),
673 triFace_(ptf.triFace_),
674 triToFace_(ptf.triToFace_),
675 triCumulativeMagSf_(ptf.triCumulativeMagSf_),
676 sumTriMagSf_(ptf.sumTriMagSf_),
677 patchNormal_(ptf.patchNormal_),
678 patchBounds_(ptf.patchBounds_),
680 eddies_(ptf.eddies_),
682 rndGen_(ptf.rndGen_),
683 sigmax_(ptf.sigmax_, mapper),
684 maxSigmaX_(ptf.maxSigmaX_),
687 singleProc_(ptf.singleProc_),
688 writeEddies_(ptf.writeEddies_)
711 nCellPerEddy_(
dict.getOrDefault<label>(
"nCellPerEddy", 5)),
716 triCumulativeMagSf_(),
719 patchBounds_(
boundBox::invertedBox),
724 sigmax_(size(),
Zero),
729 writeEddies_(
dict.getOrDefault(
"writeEddies", false))
733 const scalar t = db().time().timeOutputValue();
757 nCellPerEddy_(ptf.nCellPerEddy_),
759 patchArea_(ptf.patchArea_),
760 triFace_(ptf.triFace_),
761 triToFace_(ptf.triToFace_),
762 triCumulativeMagSf_(ptf.triCumulativeMagSf_),
763 sumTriMagSf_(ptf.sumTriMagSf_),
764 patchNormal_(ptf.patchNormal_),
765 patchBounds_(ptf.patchBounds_),
767 eddies_(ptf.eddies_),
769 rndGen_(ptf.rndGen_),
770 sigmax_(ptf.sigmax_),
771 maxSigmaX_(ptf.maxSigmaX_),
774 singleProc_(ptf.singleProc_),
775 writeEddies_(ptf.writeEddies_)
797 nCellPerEddy_(ptf.nCellPerEddy_),
799 patchArea_(ptf.patchArea_),
800 triFace_(ptf.triFace_),
801 triToFace_(ptf.triToFace_),
802 triCumulativeMagSf_(ptf.triCumulativeMagSf_),
803 sumTriMagSf_(ptf.sumTriMagSf_),
804 patchNormal_(ptf.patchNormal_),
805 patchBounds_(ptf.patchBounds_),
807 eddies_(ptf.eddies_),
809 rndGen_(ptf.rndGen_),
810 sigmax_(ptf.sigmax_),
811 maxSigmaX_(ptf.maxSigmaX_),
814 singleProc_(ptf.singleProc_),
815 writeEddies_(ptf.writeEddies_)
836 <<
"Reynolds stress " <<
R <<
" at face " << facei
837 <<
" does not obey the constraint: R_xx > 0"
841 const scalar a_xx =
sqrt(
R.xx());
843 const scalar a_xy =
R.xy()/a_xx;
845 const scalar a_yy_2 =
R.yy() -
sqr(a_xy);
850 <<
"Reynolds stress " <<
R <<
" at face " << facei
851 <<
" leads to an invalid Cholesky decomposition due to the "
852 <<
"constraint R_yy - sqr(a_xy) >= 0"
858 const scalar a_xz =
R.xz()/a_xx;
860 const scalar a_yz = (
R.yz() - a_xy*a_xz)/a_yy;
862 const scalar a_zz_2 =
R.zz() -
sqr(a_xz) -
sqr(a_yz);
867 <<
"Reynolds stress " <<
R <<
" at face " << facei
868 <<
" leads to an invalid Cholesky decomposition due to the "
869 <<
"constraint R_zz - sqr(a_xz) - sqr(a_yz) >= 0"
878 <<
" a_xx:" << a_xx <<
" a_xy:" << a_xy <<
" a_xz:" << a_xy
879 <<
" a_yy:" << a_yy <<
" a_yz:" << a_yz
891 const fvPatchFieldMapper& m
921 const auto& dfsemptf =
922 refCast<const turbulentDFSEMInletFvPatchVectorField>(ptf);
926 U_->rmap(dfsemptf.U_(), addr);
930 R_->rmap(dfsemptf.R_(), addr);
934 L_->rmap(dfsemptf.L_(), addr);
937 sigmax_.rmap(dfsemptf.sigmax_, addr);
948 if (curTimeIndex_ == -1)
958 if (curTimeIndex_ != db().time().
timeIndex())
960 tmp<vectorField>
UMean =
961 U_->value(db().time().timeOutputValue())/Uref_;
971 const scalar deltaT = db().time().deltaTValue();
972 convectEddies(UBulk, deltaT);
991 U[faceI] +=
c*uPrimeEddy(eddies_, Cf[faceI]);
999 U[faceI] +=
c*uPrimeEddy(eddies_, Cf[faceI]);
1004 calcOverlappingProcEddies(overlappingEddies);
1006 forAll(overlappingEddies, procI)
1008 const List<eddy>& eddies = overlappingEddies[procI];
1014 U[faceI] +=
c*uPrimeEddy(eddies, Cf[faceI]);
1021 const scalar fCorr =
1022 gSum((UBulk & patchNormal_)*
patch().magSf())
1027 curTimeIndex_ = db().time().timeIndex();
1036 Info<<
"Magnitude of bulk velocity: " << UBulk <<
endl;
1038 label
n = eddies_.size();
1042 Info<<
"Patch:" <<
patch().patch().name()
1043 <<
" min/max(U):" <<
gMin(
U) <<
", " <<
gMax(
U)
1046 if (db().time().writeTime())
1048 writeLumleyCoeffs();
1053 fixedValueFvPatchVectorField::updateCoeffs();
1081 writeEntry(
"value",
os);
1092 turbulentDFSEMInletFvPatchVectorField