76 void Foam::interfaceTrackingFvMesh::initializeData()
80 const word fsPatchName(
motion().get<word>(
"fsPatchName"));
87 <<
"Patch name " << fsPatchName <<
" not found." 91 fsPatchIndex_ =
patch.index();
95 if (!pointNormalsCorrectionPatches_.empty())
99 for (
const word& patchName : pointNormalsCorrectionPatches_)
106 <<
"Patch name '" << patchName
107 <<
"' for point normals correction does not exist" 116 if (!normalMotionDir_)
126 "nonReflectingFreeSurfacePatches",
127 nonReflectingFreeSurfacePatches_
132 void Foam::interfaceTrackingFvMesh::makeUs()
const 135 <<
"making free-surface velocity field" <<
nl;
140 <<
"free-surface velocity field already exists" 155 == wedgeFaPatch::typeName
158 patchFieldTypes[patchI] =
159 wedgeFaPatchVectorField::typeName;
163 label ngbPolyPatchID =
164 aMesh().boundary()[patchI].ngbPolyPatchIndex();
166 if (ngbPolyPatchID != -1)
171 == wallFvPatch::typeName
174 patchFieldTypes[patchI] =
175 slipFaPatchVectorField::typeName;
181 for (
const word& patchName : fixedFreeSurfacePatches_)
183 const label fixedPatchID =
184 aMesh().boundary().findPatchID(patchName);
186 if (fixedPatchID == -1)
189 <<
"Wrong faPatch name '" << patchName
190 <<
"' in the fixedFreeSurfacePatches list" 191 <<
" defined in the dynamicMeshDict dictionary" 195 label ngbPolyPatchID =
196 aMesh().boundary()[fixedPatchID].ngbPolyPatchIndex();
198 if (ngbPolyPatchID != -1)
203 == wallFvPatch::typeName
206 patchFieldTypes[fixedPatchID] =
207 fixedValueFaPatchVectorField::typeName;
212 UsPtr_ = std::make_unique<areaVectorField>
227 for (
const word& patchName : fixedFreeSurfacePatches_)
229 const label fixedPatchID = aMesh().boundary().findPatchID(patchName);
231 if (fixedPatchID == -1)
234 <<
"Wrong faPatch name '" << patchName
235 <<
"' in the fixedFreeSurfacePatches list" 236 <<
" defined in the dynamicMeshDict dictionary" 240 label ngbPolyPatchID =
241 aMesh().boundary()[fixedPatchID].ngbPolyPatchIndex();
243 if (ngbPolyPatchID != -1)
248 == wallFvPatch::typeName
251 UsPtr_->boundaryFieldRef()[fixedPatchID] ==
Zero;
258 void Foam::interfaceTrackingFvMesh::makeFsNetPhi()
const 261 <<
"making free-surface net flux" <<
nl;
266 <<
"free-surface net flux already exists" 270 fsNetPhiPtr_ = std::make_unique<areaScalarField>
286 void Foam::interfaceTrackingFvMesh::makeControlPoints()
289 <<
"making control points" <<
nl;
291 if (controlPointsPtr_)
294 <<
"control points already exists" 310 Info<<
"Reading control points" <<
endl;
311 controlPointsPtr_ = std::make_unique<vectorIOField>(pointsIO);
317 Info<<
"Creating new control points" <<
endl;
318 controlPointsPtr_ = std::make_unique<vectorIOField>
321 aMesh().areaCentres().internalField()
324 initializeControlPointsPosition();
329 void Foam::interfaceTrackingFvMesh::makeMotionPointsMask()
332 <<
"making motion points mask" <<
nl;
334 if (motionPointsMaskPtr_)
337 <<
"motion points mask already exists" 341 motionPointsMaskPtr_ = std::make_unique<labelList>
354 == processorFaPatch::typeName
358 aMesh().boundary()[patchI].pointLabels();
360 forAll(patchPoints, pointI)
362 motionPointsMask()[patchPoints[pointI]] = -1;
368 for (
const word& patchName : fixedFreeSurfacePatches_)
370 const label fixedPatchID = aMesh().boundary().findPatchID(patchName);
372 if (fixedPatchID == -1)
375 <<
"Wrong faPatch name in the fixedFreeSurfacePatches list" 376 <<
" defined in the dynamicMeshDict dictionary" 381 aMesh().boundary()[fixedPatchID].pointLabels();
383 forAll(patchPoints, pointI)
385 motionPointsMask()[patchPoints[pointI]] = 0;
391 void Foam::interfaceTrackingFvMesh::makeDirections()
394 <<
"make displacement directions for points and control points" <<
nl;
396 if (pointsDisplacementDirPtr_ || facesDisplacementDirPtr_)
399 <<
"points, control points displacement directions already exist" 403 pointsDisplacementDirPtr_ =
404 std::make_unique<vectorField>
410 facesDisplacementDirPtr_ =
411 std::make_unique<vectorField>
417 if (!normalMotionDir())
419 if (
mag(motionDir_) < SMALL)
422 <<
"Zero motion direction" 426 facesDisplacementDir() = motionDir_;
427 pointsDisplacementDir() = motionDir_;
430 updateDisplacementDirections();
434 void Foam::interfaceTrackingFvMesh::makePhis()
437 <<
"making free-surface flux" <<
nl;
442 <<
"free-surface flux already exists" 446 phisPtr_ = std::make_unique<edgeScalarField>
461 void Foam::interfaceTrackingFvMesh::makeSurfactConc()
const 464 <<
"making free-surface surfactant concentration field" <<
nl;
469 <<
"free-surface surfactant concentration field already exists" 473 surfactConcPtr_ = std::make_unique<areaScalarField>
492 void Foam::interfaceTrackingFvMesh::makeBulkSurfactConc()
const 495 <<
"making volume surfactant concentration field" <<
nl;
497 if (bulkSurfactConcPtr_)
500 <<
"volume surfactant concentration field already exists" 504 bulkSurfactConcPtr_ = std::make_unique<volScalarField>
520 auto& bulkSurfactConc = *bulkSurfactConcPtr_;
525 bulkSurfactConc = surfactant().bulkConc();
526 bulkSurfactConc.correctBoundaryConditions();
531 void Foam::interfaceTrackingFvMesh::makeSurfaceTension()
const 534 <<
"making surface tension field" <<
nl;
536 if (surfaceTensionPtr_)
539 <<
"surface tension field already exists" 543 surfaceTensionPtr_ = std::make_unique<areaScalarField>
553 sigma() + surfactant().dSigma(surfactantConcentration())/rho_
558 void Foam::interfaceTrackingFvMesh::makeSurfactant()
const 561 <<
"making surfactant properties" <<
nl;
566 <<
"surfactant properties already exists" 571 motion().
subDict(
"surfactantProperties");
573 surfactantPtr_ = std::make_unique<surfactantProperties>(surfactProp);
577 void Foam::interfaceTrackingFvMesh::makeContactAngle()
580 <<
"making contact angle field" <<
nl;
582 if (contactAnglePtr_)
585 <<
"contact angle already exists" 601 Info<<
"Reading contact angle field" <<
endl;
604 std::make_unique<areaScalarField>(contactAngleHeader, aMesh());
609 void Foam::interfaceTrackingFvMesh::updateDisplacementDirections()
611 if (normalMotionDir())
614 pointsDisplacementDir() = aMesh().pointAreaNormals();
619 if (contactAnglePtr_)
621 label ngbPolyPatchID =
622 aMesh().boundary()[patchI].ngbPolyPatchIndex();
624 if (ngbPolyPatchID != -1)
629 == wallFvPatch::typeName
633 aMesh().boundary()[patchI].pointLabels();
638 .ngbPolyPatchPointNormals()
641 forAll(patchPoints, pointI)
643 pointsDisplacementDir()[patchPoints[pointI]] -=
647 & pointsDisplacementDir()[patchPoints[pointI]]
650 pointsDisplacementDir()[patchPoints[pointI]] /=
653 pointsDisplacementDir()
665 facesDisplacementDir() =
666 aMesh().faceAreaNormals().internalField();
669 const vectorField& Cf = aMesh().areaCentres().internalField();
672 facesDisplacementDir()
673 *(facesDisplacementDir()&(controlPoints() - Cf))
679 void Foam::interfaceTrackingFvMesh::initializeControlPointsPosition()
682 const faceList& faces = aMesh().faces();
687 correctPointDisplacement(sweptVolCorr, displacement);
695 sweptVol[faceI] = -faces[faceI].sweptVol(
points, newPoints);
702 faceArea[faceI] = faces[faceI].unitNormal(newPoints);
709 deltaH[faceI] = sweptVol[faceI]/
710 ((faceArea[faceI] & facesDisplacementDir()[faceI]) + SMALL);
712 if (
mag(faceArea[faceI] & facesDisplacementDir()[faceI]) < SMALL)
719 <<
"Something is wrong with specified motion direction" 724 for (
const word& patchName : fixedFreeSurfacePatches_)
726 label fixedPatchID = aMesh().boundary().findPatchID(patchName);
728 if (fixedPatchID == -1)
731 <<
"Wrong faPatch name in the fixedFreeSurfacePatches list" 732 <<
" defined in the freeSurfaceProperties dictionary" 739 : aMesh().
boundary()[fixedPatchID].edgeFaces()
742 deltaH[facei] *= 2.0;
746 controlPoints() += facesDisplacementDir()*deltaH;
751 void Foam::interfaceTrackingFvMesh::smoothFreeSurfaceMesh()
753 Info<<
"Smoothing free surface mesh" <<
endl;
755 controlPoints() = aMesh().areaCentres().internalField();
759 const faceList& faces = aMesh().faces();
767 sweptVol[faceI] = -faces[faceI].sweptVol(
points, newPoints);
773 faceArea[faceI] = faces[faceI].unitNormal(newPoints);
778 sweptVol/(faceArea & facesDisplacementDir())
781 for (
const word& patchName : fixedFreeSurfacePatches_)
783 label fixedPatchID = aMesh().boundary().findPatchID(patchName);
785 if (fixedPatchID == -1)
788 <<
"Wrong faPatch name fixedFreeSurfacePatches list" 789 <<
" defined in the dynamicMeshDict dictionary" 796 : aMesh().
boundary()[fixedPatchID].edgeFaces()
799 deltaHf[facei] *= 2.0;
803 controlPoints() += facesDisplacementDir()*deltaHf;
805 displacement = pointDisplacement();
808 refCast<velocityMotionSolver>
816 fixedValuePointPatchVectorField& fsPatchPointMeshU =
817 refCast<fixedValuePointPatchVectorField>
831 void Foam::interfaceTrackingFvMesh::updateSurfaceFlux()
837 void Foam::interfaceTrackingFvMesh::updateSurfactantConcentration()
839 if (!pureFreeSurface())
849 +
fam::div(Phis(), surfactantConcentration())
852 surfactant().diffusion(),
853 surfactantConcentration()
857 if (surfactant().soluble())
877 bulkSurfactantConcentration().boundaryField()[fsPatchIndex()];
878 Cb.correctBoundaryConditions();
883 surfactant().adsorptionCoeff()*
Cb 884 + surfactant().adsorptionCoeff()
885 *surfactant().desorptionCoeff(),
886 surfactantConcentration()
888 - surfactant().adsorptionCoeff()
889 *
Cb*surfactant().saturatedConc();
897 sigma() + surfactant().dSigma(surfactantConcentration())/rho_;
899 if (
neg(
min(surfaceTension().internalField().
field())))
902 <<
"Surface tension is negative" 909 Foam::vector Foam::interfaceTrackingFvMesh::totalPressureForce()
const 913 const vectorField&
n = aMesh().faceAreaNormals().internalField();
919 return gSum(pressureForces);
923 Foam::vector Foam::interfaceTrackingFvMesh::totalViscousForce()
const 939 const vectorField&
n = aMesh().faceAreaNormals().internalField();
943 U().boundaryField()[fsPatchIndex()].
snGrad()
956 return gSum(viscousForces);
960 Foam::vector Foam::interfaceTrackingFvMesh::totalSurfaceTensionForce()
const 964 const vectorField&
n = aMesh().faceAreaNormals().internalField();
966 const scalarField&
K = aMesh().faceCurvatures().internalField();
970 if (pureFreeSurface())
976 aMesh().Le()*aMesh().edgeLengthCorrection()
981 surfTensionForces = surfaceTension().internalField().field()*
K*S*
n;
984 return gSum(surfTensionForces);
988 Foam::scalar Foam::interfaceTrackingFvMesh::maxCourantNumber()
992 if (pureFreeSurface())
998 mesh().time().deltaTValue()/
1017 mesh().time().deltaTValue()/
1029 void Foam::interfaceTrackingFvMesh::updateProperties()
1034 "transportProperties" 1043 void Foam::interfaceTrackingFvMesh::correctPointDisplacement
1050 aMesh().patch().pointFaces();
1053 aMesh().patch().localFaces();
1056 aMesh().patch().localPoints();
1058 for (
const word& patchName : fixedFreeSurfacePatches_)
1060 label fixedPatchID = aMesh().boundary().findPatchID(patchName);
1063 aMesh().boundary()[fixedPatchID].pointLabels();
1066 aMesh().boundary()[fixedPatchID].edgeFaces();
1072 label curFace = eFaces[edgeI];
1074 const labelList& curPoints = faces[curFace];
1076 forAll(curPoints, pointI)
1078 label curPoint = curPoints[pointI];
1079 label index = pLabels.
find(curPoint);
1092 forAll(corrPoints, pointI)
1094 label curPoint = corrPoints[pointI];
1100 label curFace =
pFaces[curPoint][faceI];
1102 label index = eFaces.
find(curFace);
1113 forAll(corrPoints, pointI)
1115 label curPoint = corrPoints[pointI];
1119 const labelList& curPointFaces = corrPointFaces[pointI];
1121 forAll(curPointFaces, faceI)
1123 const face& curFace = faces[curPointFaces[faceI]];
1125 label ptInFace = curFace.
which(curPoint);
1126 label next = curFace.
nextLabel(ptInFace);
1127 label prev = curFace.
prevLabel(ptInFace);
1131 const vector&
c = pointsDisplacementDir()[curPoint];
1133 curDisp += 2*sweptVolCorr[curPointFaces[faceI]]/((a^
b)&
c);
1136 curDisp /= curPointFaces.
size();
1138 displacement[curPoint] =
1139 curDisp*pointsDisplacementDir()[curPoint];
1144 for (
const word& patchName : nonReflectingFreeSurfacePatches_)
1146 label nonReflectingPatchID =
1147 aMesh().boundary().findPatchID(patchName);
1150 aMesh().boundary()[nonReflectingPatchID].pointLabels();
1153 aMesh().boundary()[nonReflectingPatchID].edgeFaces();
1159 forAll(corrPoints, pointI)
1161 label curPoint = corrPoints[pointI];
1167 label curFace =
pFaces[curPoint][faceI];
1169 label index = eFaces.
find(curFace);
1181 forAll(corrPoints, pointI)
1183 label curPoint = corrPoints[pointI];
1187 const labelList& curPointFaces = corrPointFaces[pointI];
1189 forAll(curPointFaces, faceI)
1191 const face& curFace = faces[curPointFaces[faceI]];
1193 label ptInFace = curFace.
which(curPoint);
1194 label next = curFace.
nextLabel(ptInFace);
1195 label prev = curFace.
prevLabel(ptInFace);
1201 if (corrPoints.
find(next) == -1)
1216 vector c0 = displacement[p1];
1218 scalar V0 =
mag((
a0^b0)&c0)/2;
1220 scalar DV = sweptVolCorr[curPointFaces[faceI]] - V0;
1222 if (corrPoints.
find(prev) != -1)
1226 (
points[next] + displacement[next])
1228 const vector&
c = pointsDisplacementDir()[curPoint];
1230 curDisp += 2*DV/((a^
b)&
c);
1235 - (
points[prev] + displacement[prev]);
1237 const vector&
c = pointsDisplacementDir()[curPoint];
1239 curDisp += 2*DV/((a^
b)&
c);
1243 curDisp /= curPointFaces.size();
1245 displacement[curPoint] =
1246 curDisp*pointsDisplacementDir()[curPoint];
1252 void Foam::interfaceTrackingFvMesh::correctContactLinePointNormals()
1260 aMesh().pointAreaNormals()
1263 if (contactAnglePtr_ && correctContactLineNormals())
1265 Info<<
"Correcting contact line normals" <<
endl;
1269 const labelList& meshPoints = aMesh().patch().meshPoints();
1280 aMesh().thisDb().newIOobject(
"tangent"),
1287 const labelListList& edgeFaces = aMesh().patch().edgeFaces();
1288 const labelListList& pointEdges = aMesh().patch().pointEdges();
1289 const labelListList& pointFaces = aMesh().patch().pointFaces();
1290 const edgeList& edges = aMesh().edges();
1297 == processorFaPatch::typeName
1301 refCast<const processorFaPatch>
1303 aMesh().boundary()[patchI]
1309 forAll(patchPointLabels, pointI)
1311 label curPoint = patchPointLabels[pointI];
1318 const labelList& curPointEdges = pointEdges[curPoint];
1320 forAll(curPointEdges, edgeI)
1322 label curEdge = curPointEdges[edgeI];
1324 if (edgeFaces[curEdge].size() == 1)
1329 aMesh().boundary()[pI];
1331 label index = curEdges.
find(curEdge);
1338 != processorFaPatch::typeName
1355 vector t = edges[curEdge].vec(oldPoints);
1356 t /=
mag(t) + SMALL;
1359 pointFaces[curPoint];
1361 forAll(curPointFaces, fI)
1363 tangent.ref().field()[curPointFaces[fI]] = t;
1370 tangent.correctBoundaryConditions();
1375 label ngbPolyPatchID =
1376 aMesh().boundary()[patchI].ngbPolyPatchIndex();
1378 if (ngbPolyPatchID != -1)
1383 == wallFvPatch::typeName
1391 - contactAnglePtr_->boundaryField()[patchI]
1397 aMesh().
boundary()[patchI].ngbPolyPatchPointNormals()
1401 aMesh().boundary()[patchI].pointLabels();
1406 rotationAxis /=
mag(rotationAxis) + SMALL;
1411 const edgeList& edges = aMesh().edges();
1414 aMesh().boundary()[patchI].pointEdges();
1416 forAll(pointEdges, pointI)
1420 forAll(pointEdges[pointI], eI)
1423 aMesh().boundary()[patchI].start()
1424 + pointEdges[pointI][eI];
1426 vector e = edges[curEdge].vec(oldPoints);
1428 e *= (
e&rotationAxis[pointI])
1429 /
mag(
e&rotationAxis[pointI]);
1431 e /=
mag(
e) + SMALL;
1436 if (pointEdges[pointI].size() == 1)
1438 label curPoint = patchPoints[pointI];
1441 aMesh().patch().pointEdges();
1445 label procPatchID = -1;
1449 aMesh().patch().edgeFaces();
1451 forAll(curPointEdges, edgeI)
1453 label curEdge = curPointEdges[edgeI];
1455 if (edgeFaces[curEdge].size() == 1)
1460 aMesh().boundary()[pI];
1463 curEdges.
find(curEdge);
1470 == processorFaPatch::typeName
1482 if (procPatchID != -1)
1485 tangent.boundaryField()[procPatchID]
1486 .patchNeighbourField()()[
edgeID];
1488 t *= (t&rotationAxis[pointI])
1489 /(
mag(t&rotationAxis[pointI]) + SMALL);
1491 t /=
mag(t) + SMALL;
1497 rotationAxis[pointI] = rotAx/(
mag(rotAx) + SMALL);
1501 ngbN = ngbN*
cos(rotAngle)
1502 + rotationAxis*(rotationAxis & ngbN)*(1 -
cos(rotAngle))
1503 + (rotationAxis^ngbN)*
sin(rotAngle);
1506 forAll(patchPoints, pointI)
1508 N[patchPoints[pointI]] -=
1509 ngbN[pointI]*(ngbN[pointI]&
N[patchPoints[pointI]]);
1511 N[patchPoints[pointI]] /=
1512 mag(
N[patchPoints[pointI]]) + SMALL;
1525 Foam::interfaceTrackingFvMesh::interfaceTrackingFvMesh
1533 fixedFreeSurfacePatches_(),
1534 nonReflectingFreeSurfacePatches_(),
1535 pointNormalsCorrectionPatches_(),
1536 normalMotionDir_(
false),
1539 pureFreeSurface_(true),
1540 rigidFreeSurface_(
false),
1541 correctContactLineNormals_(
false),
1602 aMeshPtr_.reset(
new faMesh(*
this));
1605 fixedFreeSurfacePatches_ =
1606 motion().get<
wordList>(
"fixedFreeSurfacePatches");
1608 pointNormalsCorrectionPatches_ =
1609 motion().
get<
wordList>(
"pointNormalsCorrectionPatches");
1611 normalMotionDir_ = motion().
get<
bool>(
"normalMotionDir");
1612 smoothing_ = motion().getOrDefault(
"smoothing",
false);
1613 pureFreeSurface_ = motion().getOrDefault(
"pureFreeSurface",
true);
1650 return *fsNetPhiPtr_;
1661 return *fsNetPhiPtr_;
1667 forAll(
Us().boundaryField(), patchI)
1671 Us().boundaryField()[patchI].
type()
1672 == calculatedFaPatchVectorField::typeName
1677 pUs =
Us().boundaryField()[patchI].patchInternalField();
1679 label ngbPolyPatchID =
1680 aMesh().boundary()[patchI].ngbPolyPatchIndex();
1682 if (ngbPolyPatchID != -1)
1687 U().boundaryField()[ngbPolyPatchID].
type()
1688 == slipFvPatchVectorField::typeName
1692 U().boundaryField()[ngbPolyPatchID].
type()
1693 == symmetryFvPatchVectorField::typeName
1699 aMesh().
boundary()[patchI].ngbPolyPatchFaceNormals()
1708 Us().correctBoundaryConditions();
1716 Us().ref().field() =
U().boundaryField()[fsPatchIndex()];
1724 correctUsBoundaryConditions();
1730 return *getObjectPtr<const volVectorField>(
"U");
1736 return *getObjectPtr<const volScalarField>(
"p");
1742 return *getObjectPtr<const surfaceScalarField>(
"phi");
1750 auto& SnGradU = tSnGradU.ref();
1752 const vectorField& nA = aMesh().faceAreaNormals().internalField();
1757 - aMesh().faceCurvatures()*(aMesh().faceAreaNormals()&
Us())
1764 gradUs -=
n*(
n & gradUs);
1765 gradUs.correctBoundaryConditions();
1774 if (!pureFreeSurface() &&
max(
nu) > SMALL)
1776 tangentialSurfaceTensionForce =
1777 surfaceTensionGrad()().internalField();
1781 tangentialSurfaceTensionForce/(
nu + SMALL)
1782 - nA*divUs.internalField()
1783 - (gradUs.internalField()&nA);
1793 auto& SnGradUn = tSnGradUn.ref();
1798 - aMesh().faceCurvatures()*(aMesh().faceAreaNormals()&
Us())
1811 auto& pressureJump = tPressureJump.ref();
1813 const scalarField&
K = aMesh().faceCurvatures().internalField();
1825 + 2.0*
nu*freeSurfaceSnGradUn();
1827 if (pureFreeSurface())
1833 pressureJump -= surfaceTension().internalField()*
K;
1836 return tPressureJump;
1842 if (!controlPointsPtr_)
1844 makeControlPoints();
1847 return *controlPointsPtr_;
1853 if (!motionPointsMaskPtr_)
1855 makeMotionPointsMask();
1858 return *motionPointsMaskPtr_;
1864 if (!pointsDisplacementDirPtr_)
1869 return *pointsDisplacementDirPtr_;
1875 if (!facesDisplacementDirPtr_)
1880 return *facesDisplacementDirPtr_;
1897 if (!surfactConcPtr_)
1902 return *surfactConcPtr_;
1909 if (!surfactConcPtr_)
1914 return *surfactConcPtr_;
1921 if (!bulkSurfactConcPtr_)
1923 makeBulkSurfactConc();
1926 return *bulkSurfactConcPtr_;
1933 if (!bulkSurfactConcPtr_)
1935 makeBulkSurfactConc();
1938 return *bulkSurfactConcPtr_;
1945 if (!surfaceTensionPtr_)
1947 makeSurfaceTension();
1950 return *surfaceTensionPtr_;
1957 if (!surfaceTensionPtr_)
1959 makeSurfaceTension();
1962 return *surfaceTensionPtr_;
1969 if (!surfactantPtr_)
1974 return *surfactantPtr_;
1985 "surfaceTensionGrad",
1997 auto&
grad = tgrad.ref();
2002 grad.correctBoundaryConditions();
2012 if (smoothing_ && !rigidFreeSurface_)
2014 smoothFreeSurfaceMesh();
2015 clearControlPoints();
2018 updateDisplacementDirections();
2022 Info<<
"Maximal capillary Courant number: " 2023 << maxCourantNumber() <<
endl;
2025 const scalarField&
K = aMesh().faceCurvatures().internalField();
2029 Info<<
"Free surface curvature: min = " <<
limits.min()
2030 <<
", max = " <<
limits.max()
2036 if (!rigidFreeSurface_)
2040 phi().boundaryField()[fsPatchIndex()];
2052 Info<<
"Free surface continuity error : sum local = " 2053 <<
gSum(
mag(sweptVolCorr)) <<
", global = " <<
gSum(sweptVolCorr)
2057 fsNetPhi().ref().field() = sweptVolCorr;
2063 "ddt(" +
U().
name() +
')' 2101 <<
"Unsupported temporal differencing scheme : " 2107 const vectorField& Nf = aMesh().faceAreaNormals().internalField();
2111 sweptVolCorr/(Sf*(Nf & facesDisplacementDir()))
2114 for (
const word& patchName : fixedFreeSurfacePatches_)
2116 label fixedPatchID =
2117 aMesh().boundary().findPatchID(patchName);
2119 if (fixedPatchID == -1)
2122 <<
"Wrong faPatch name '" << patchName
2123 <<
"'in the fixedFreeSurfacePatches list" 2124 <<
" defined in dynamicMeshDict dictionary" 2131 : aMesh().
boundary()[fixedPatchID].edgeFaces()
2134 deltaHf[facei] *= 2.0;
2138 controlPoints() += facesDisplacementDir()*deltaHf;
2140 pointField displacement(pointDisplacement());
2141 correctPointDisplacement(sweptVolCorr, displacement);
2144 refCast<velocityMotionSolver>
2152 fixedValuePointPatchVectorField& fsPatchPointMeshU =
2153 refCast<fixedValuePointPatchVectorField>
2165 correctContactLinePointNormals();
2176 refCast<velocityMotionSolver>
2184 fixedValuePointPatchVectorField& fsPatchPointMeshU =
2185 refCast<fixedValuePointPatchVectorField>
2200 updateSurfactantConcentration();
2212 mesh().time().timePath()/
"freeSurface",
2224 mesh().time().timePath()/
"freeSurfaceControlPoints.vtk" 2227 Info<<
"Writing free surface control points to " << os.name() <<
nl;
2229 os <<
"# vtk DataFile Version 2.0" <<
nl 2230 <<
"freeSurfaceControlPoints" <<
nl 2232 <<
"DATASET POLYDATA" <<
nl;
2234 const label
nPoints = controlPoints().size();
2236 os <<
"POINTS " <<
nPoints <<
" float" <<
nl;
2237 for (
const point&
p : controlPoints())
2239 os << float(
p.x()) <<
' ' 2240 <<
float(
p.y()) <<
' ' 2241 <<
float(
p.z()) <<
nl;
2245 for (label
id = 0;
id <
nPoints; ++id)
2247 os << 1 <<
' ' <<
id <<
nl;
edgeScalarField & Phis()
Return free-surface fluid flux field.
virtual bool init(const bool doInit)
Initialise all non-demand-driven data.
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Write concrete PrimitivePatch faces/points (optionally with fields) as a vtp file or a legacy vtk fil...
tmp< fvMatrix< Type > > correction(const fvMatrix< Type > &)
Return the correction form of the given matrix by subtracting the matrix multiplied by the current fi...
const Type & value() const noexcept
Return const reference to value.
Second-oder Crank-Nicolson implicit ddt using the current and previous time-step fields as well as th...
void size(const label n)
Older name for setAddressableSize.
const Type & lookupObject(const word &name, const bool recursive=false) const
Lookup and return const reference to the object of the given Type. Fatal if not found or the wrong ty...
vectorField & facesDisplacementDir()
Return reference to control points displacement direction field.
scalar deltaTValue() const noexcept
Return time step value.
A face is a list of labels corresponding to mesh vertices.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
virtual bool writeGeometry()
Write vertex topology.
CGAL::indexedCell< K > Cb
const areaScalarField & fsNetPhi() const
Return free-surface net flux.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const surfaceVectorField & Cf() const
Return face centres as surfaceVectorField.
Virtual base class for velocity motion solver.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
static tmp< GeometricField< Type, faePatchField, edgeMesh > > interpolate(const GeometricField< Type, faPatchField, areaMesh > &tvf, const edgeScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
Unit conversion functions.
const Internal & internalField() const noexcept
Return a const-reference to the dimensioned internal field.
Output to file stream as an OSstream, normally using std::ofstream for the actual output...
tmp< scalarField > freeSurfacePressureJump()
Return free surface pressure jump.
constexpr char nl
The newline '\n' character (0x0a)
vectorField & pointsDisplacementDir()
Return reference to point displacement direction field.
tmp< GeometricField< Type, faPatchField, areaMesh > > div(const GeometricField< Type, faePatchField, edgeMesh > &ssf)
virtual bool update()
Update the mesh for both mesh motion and topology change.
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface...
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
void updateUs()
Update free-surface velocity field.
const labelList & pointLabels() const
Return patch point labels.
static bool & parRun() noexcept
Test if this a parallel run.
An indexed form of CGAL::Triangulation_cell_base_3<K> used to keep track of the Delaunay cells (tets)...
label nextLabel(const label i) const
Next vertex on face.
const volVectorField & U() const
Return constant reference to velocity field.
Virtual base class for mesh motion solver.
void correctUsBoundaryConditions()
Correct surface velocity boundary conditions.
Ignore writing from objectRegistry::writeObject()
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
const dimensionSet dimless
Dimensionless.
const Time & time() const
Return the top-level database.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
CGAL::Exact_predicates_exact_constructions_kernel K
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Abstract base class for turbulence models (RAS, LES and laminar).
dimensionedScalar sigma("sigma", dimMass/sqr(dimTime), transportProperties)
faMesh & aMesh()
Return reference to finite area mesh.
dimensionedScalar neg(const dimensionedScalar &ds)
static const word & zeroGradientType() noexcept
The type name for zeroGradient patch fields.
Macros for easy insertion into run-time selection tables.
bool get(const label i) const
Return bool value at specified position, always false for out-of-range access.
#define forAll(list, i)
Loop across all elements in list.
tmp< faMatrix< Type > > laplacian(const GeometricField< Type, faPatchField, areaMesh > &vf)
label prevLabel(const label i) const
Previous vertex on face.
volScalarField & bulkSurfactantConcentration()
Return volume surfactant concentration field.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
const dimensionSet dimVolume(pow3(dimLength))
zeroField Sp(const Foam::zero, const GeometricField< Type, faPatchField, areaMesh > &)
A no-op source.
virtual bool init(const bool doInit)
Initialise all non-demand-driven data.
label findPatchID(const word &patchName, const bool allowNotFound=true) const
Find patch index given a name, return -1 if not found.
tmp< GeometricField< Type, faePatchField, edgeMesh > > linearEdgeInterpolate(const GeometricField< Type, faPatchField, areaMesh > &vf)
const dimensionedScalar e
Elementary charge.
Type gSum(const FieldField< Field, Type > &f)
dimensionedScalar cos(const dimensionedScalar &ds)
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
* ~interfaceTrackingFvMesh()
Destructor.
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
A class for handling words, derived from Foam::string.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
#define DebugInFunction
Report an information message using Foam::Info.
label size() const noexcept
The number of entries in the list.
areaVectorField & Us()
Return free-surface velocity field.
virtual const pointField & oldPoints() const
Return old points (mesh motion)
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
label which(const label vertex) const
Find local vertex on face for the vertex label, same as find()
MinMax< Type > gMinMax(const FieldField< Field, Type > &f)
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::HEX);labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells].reset(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} pointMap[start]=pointMap[end]=Foam::min(start, end);} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};constexpr label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< DynamicList< face > > pFaces[nBCs]
label timeIndex() const noexcept
Return the current time index.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Second-order backward-differencing ddt using the current and two previous time-step values...
errorManip< error > abort(error &err)
vectorField & controlPoints()
Return control points.
label find(const T &val) const
Find index of the first occurrence of the value.
virtual bool update()
Update the mesh for both mesh motion and topology change.
areaScalarField & surfactantConcentration()
Return free-surface surfactant concentration field.
tmp< faMatrix< Type > > ddt(const GeometricField< Type, faPatchField, areaMesh > &vf)
const uniformDimensionedVectorField & g
dimensionedScalar sin(const dimensionedScalar &ds)
const dimensionSet dimForce
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
tmp< faMatrix< Type > > div(const edgeScalarField &flux, const GeometricField< Type, faPatchField, areaMesh > &vf, const word &name)
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
Type gAverage(const FieldField< Field, Type > &f, const label comm)
The global arithmetic average of a FieldField.
Type gMax(const FieldField< Field, Type > &f)
const dimensionSet dimMoles(0, 0, 0, 0, 1, 0, 0)
Info<< "Reading field U\"<< endl;volVectorField U(IOobject("U", runTime.timeName(), mesh, IOobject::MUST_READ, IOobject::AUTO_WRITE), mesh);volScalarField rho(IOobject("rho", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE), thermo.rho());volVectorField rhoU(IOobject("rhoU", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::NO_WRITE), rho *U);volScalarField rhoE(IOobject("rhoE", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::NO_WRITE), rho *(e+0.5 *magSqr(U)));surfaceScalarField pos(IOobject("pos", runTime.timeName(), mesh), mesh, dimensionedScalar("pos", dimless, 1.0));surfaceScalarField neg(IOobject("neg", runTime.timeName(), mesh), mesh, dimensionedScalar("neg", dimless, -1.0));surfaceScalarField phi("phi", fvc::flux(rhoU));Info<< "Creating turbulence model\"<< endl;autoPtr< compressible::turbulenceModel > turbulence(compressible::turbulenceModel::New(rho, U, phi, thermo))
defineTypeNameAndDebug(combustionModel, 0)
const volScalarField & p() const
Return constant reference to pressure field.
static const gravity & New(const word &name, const Time &runTime)
Return named gravity field cached or construct on Time.
tmp< GeometricField< Type, faPatchField, areaMesh > > edgeIntegrate(const GeometricField< Type, faePatchField, edgeMesh > &ssf)
const faBoundaryMesh & boundary() const noexcept
Return constant reference to boundary mesh.
const surfaceScalarField & phi() const
Return constant reference to velocity field.
labelList & motionPointsMask()
Return reference to motion points mask field.
const dimensionSet dimDensity
const Vector< label > N(dict.get< Vector< label >>("N"))
Calculate the mesh motion flux and convert fluxes from absolute to relative and back.
const surfactantProperties & surfactant() const
Return surfactant properties.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field values.
decomposeUsingBbs false
Use bounding boxes (default) or unique decomposition of triangles (i.e. do not duplicate triangles) ...
Ostream & flush(Ostream &os)
Flush stream.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Abstract base class for geometry and/or topology changing fvMesh.
const dimensionedScalar c
Speed of light in a vacuum.
Automatically write from objectRegistry::writeObject()
void writeVTKControlPoints()
Write VTK freeSurface control points.
const dimensionedScalar a0
Bohr radius: default SI units: [m].
Template specialisation for scalar faMatrix.
const std::string patch
OpenFOAM patch number as a std::string.
const motionSolver & motion() const
Return the motionSolver.
tmp< scalarField > freeSurfaceSnGradUn()
Return free surface normal derivative of normal velocity comp.
Legacy ASCII, legacyAsciiFormatter.
bool correctPatchPointNormals(const label patchID) const
Whether point normals should be corrected for a patch.
messageStream Info
Information stream (stdout output on master, null elsewhere)
tmp< areaVectorField > surfaceTensionGrad()
Return surface tension gradient.
The dynamicMotionSolverFvMesh.
vtk::vertexWriter writer(edgeCentres, outputOpts,(aMesh.time().globalPath()/outputName), UPstream::parRun())
List< Key > toc() const
The table of contents (the keys) in unsorted order.
void writeVTK() const
Write VTK freeSurface mesh.
A class for managing temporary objects.
tmp< vectorField > freeSurfaceSnGradU()
Return free surface normal derivative of velocity.
Basic first-order Euler implicit/explicit ddt using only the current and previous time-step values...
A simple single-phase transport model based on viscosityModel.
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Request registration (bool: true)
A primitive field of type <T> with automated input and output.
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
const volScalarField & p0
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > snGrad(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
const dimensionSet dimArea(sqr(dimLength))
tmp< GeometricField< typename outerProduct< vector, Type >::type, faPatchField, areaMesh >> grad(const GeometricField< Type, faePatchField, edgeMesh > &ssf)
areaScalarField & surfaceTension()
Return surface tension field.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
The interfaceTrackingFvMesh.
static constexpr const zero Zero
Global zero (0)
const dimensionSet dimVelocity