interfaceTrackingFvMesh.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2019 Zeljko Tukovic, FSB Zagreb.
9  Copyright (C) 2020-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
31 #include "motionSolver.H"
32 #include "volFields.H"
33 #include "wedgeFaPatch.H"
34 #include "wedgeFaPatchFields.H"
35 #include "slipFaPatchFields.H"
37 #include "slipFvPatchFields.H"
38 #include "symmetryFvPatchFields.H"
39 #include "wallFvPatch.H"
40 #include "polyPatchID.H"
41 #include "fvcMeshPhi.H"
43 #include "EulerDdtScheme.H"
44 #include "CrankNicolsonDdtScheme.H"
45 #include "backwardDdtScheme.H"
46 #include "twoDPointCorrector.H"
47 #include "gravityMeshObject.H"
49 #include "demandDrivenData.H"
50 #include "unitConversion.H"
51 #include "foamVtkUIndPatchWriter.H"
52 
53 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
54 
55 namespace Foam
56 {
59  (
62  IOobject
63  );
65  (
68  doInit
69  );
70 }
71 
72 
73 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
74 
75 void Foam::interfaceTrackingFvMesh::initializeData()
76 {
77  // Set free surface patch index
78  {
79  const word fsPatchName(motion().get<word>("fsPatchName"));
80 
81  polyPatchID patch(fsPatchName, this->boundaryMesh());
82 
83  if (!patch.active())
84  {
86  << "Patch name " << fsPatchName << " not found."
87  << abort(FatalError);
88  }
89 
90  fsPatchIndex_ = patch.index();
91  }
92 
93  // Set point normal correction for finite area mesh
94  {
96 
97  for (const word& patchName : pointNormalsCorrectionPatches_)
98  {
99  label patchID = aMesh().boundary().findPatchID(patchName);
100 
101  if (patchID == -1)
102  {
104  << "Patch name '" << patchName
105  << "' for point normals correction does not exist"
106  << abort(FatalError);
107  }
108 
109  correction[patchID] = true;
110  }
111  }
112 
113  // Read motion direction
114  if (!normalMotionDir_)
115  {
116  motionDir_ = normalised(motion().get<vector>("motionDir"));
117  }
118 
119  // Check if contact angle is defined
120  makeContactAngle();
121 
123  (
124  "nonReflectingFreeSurfacePatches",
125  nonReflectingFreeSurfacePatches_
126  );
127 }
128 
129 
130 void Foam::interfaceTrackingFvMesh::makeUs() const
131 {
133  << "making free-surface velocity field" << nl;
134 
135  if (UsPtr_)
136  {
138  << "free-surface velocity field already exists"
139  << abort(FatalError);
140  }
141 
142  wordList patchFieldTypes
143  (
144  aMesh().boundary().size(),
145  zeroGradientFaPatchVectorField::typeName
146  );
147 
148  forAll(aMesh().boundary(), patchI)
149  {
150  if
151  (
152  aMesh().boundary()[patchI].type()
153  == wedgeFaPatch::typeName
154  )
155  {
156  patchFieldTypes[patchI] =
157  wedgeFaPatchVectorField::typeName;
158  }
159  else
160  {
161  label ngbPolyPatchID =
162  aMesh().boundary()[patchI].ngbPolyPatchIndex();
163 
164  if (ngbPolyPatchID != -1)
165  {
166  if
167  (
168  mesh().boundary()[ngbPolyPatchID].type()
169  == wallFvPatch::typeName
170  )
171  {
172  patchFieldTypes[patchI] =
173  slipFaPatchVectorField::typeName;
174  }
175  }
176  }
177  }
178 
179  for (const word& patchName : fixedFreeSurfacePatches_)
180  {
181  const label fixedPatchID =
182  aMesh().boundary().findPatchID(patchName);
183 
184  if (fixedPatchID == -1)
185  {
187  << "Wrong faPatch name '" << patchName
188  << "' in the fixedFreeSurfacePatches list"
189  << " defined in the dynamicMeshDict dictionary"
190  << abort(FatalError);
191  }
192 
193  label ngbPolyPatchID =
194  aMesh().boundary()[fixedPatchID].ngbPolyPatchIndex();
195 
196  if (ngbPolyPatchID != -1)
197  {
198  if
199  (
200  mesh().boundary()[ngbPolyPatchID].type()
201  == wallFvPatch::typeName
202  )
203  {
204  patchFieldTypes[fixedPatchID] =
205  fixedValueFaPatchVectorField::typeName;
206  }
207  }
208  }
209 
210  UsPtr_ = new areaVectorField
211  (
212  IOobject
213  (
214  "Us",
215  mesh().time().timeName(),
216  mesh(),
219  ),
220  aMesh(),
222  patchFieldTypes
223  );
224 
225  for (const word& patchName : fixedFreeSurfacePatches_)
226  {
227  const label fixedPatchID = aMesh().boundary().findPatchID(patchName);
228 
229  if (fixedPatchID == -1)
230  {
232  << "Wrong faPatch name '" << patchName
233  << "' in the fixedFreeSurfacePatches list"
234  << " defined in the dynamicMeshDict dictionary"
235  << abort(FatalError);
236  }
237 
238  label ngbPolyPatchID =
239  aMesh().boundary()[fixedPatchID].ngbPolyPatchIndex();
240 
241  if (ngbPolyPatchID != -1)
242  {
243  if
244  (
245  mesh().boundary()[ngbPolyPatchID].type()
246  == wallFvPatch::typeName
247  )
248  {
249  UsPtr_->boundaryFieldRef()[fixedPatchID] == Zero;
250  }
251  }
252  }
253 }
254 
255 
256 void Foam::interfaceTrackingFvMesh::makeFsNetPhi() const
257 {
259  << "making free-surface net flux" << nl;
260 
261  if (fsNetPhiPtr_)
262  {
264  << "free-surface net flux already exists"
265  << abort(FatalError);
266  }
267 
268  fsNetPhiPtr_ = new areaScalarField
269  (
270  IOobject
271  (
272  "fsNetPhi",
273  mesh().time().timeName(),
274  mesh(),
277  ),
278  aMesh(),
280  );
281 }
282 
283 
284 void Foam::interfaceTrackingFvMesh::makeControlPoints()
285 {
287  << "making control points" << nl;
288 
289  if (controlPointsPtr_)
290  {
292  << "control points already exists"
293  << abort(FatalError);
294  }
295 
296  IOobject controlPointsHeader
297  (
298  "controlPoints",
299  mesh().time().timeName(),
300  mesh(),
302  );
303 
304  if (controlPointsHeader.typeHeaderOk<vectorIOField>())
305  {
306  Info<< "Reading control points" << endl;
307  controlPointsPtr_ =
308  new vectorIOField
309  (
310  IOobject
311  (
312  "controlPoints",
313  mesh().time().timeName(),
314  mesh(),
317  )
318  );
319  }
320  else
321  {
322  Info<< "Creating new control points" << endl;
323  controlPointsPtr_ =
324  new vectorIOField
325  (
326  IOobject
327  (
328  "controlPoints",
329  mesh().time().timeName(),
330  mesh(),
333  ),
334  aMesh().areaCentres().internalField()
335  );
336 
337  initializeControlPointsPosition();
338  }
339 }
340 
341 
342 void Foam::interfaceTrackingFvMesh::makeMotionPointsMask()
343 {
345  << "making motion points mask" << nl;
346 
347  if (motionPointsMaskPtr_)
348  {
350  << "motion points mask already exists"
351  << abort(FatalError);
352  }
353 
354  motionPointsMaskPtr_ = new labelList
355  (
356  mesh().boundaryMesh()[fsPatchIndex()].nPoints(),
357  1
358  );
359 
360  // Mark free surface boundary points
361  // that belong to processor patches
362  forAll(aMesh().boundary(), patchI)
363  {
364  if
365  (
366  aMesh().boundary()[patchI].type()
367  == processorFaPatch::typeName
368  )
369  {
370  const labelList& patchPoints =
371  aMesh().boundary()[patchI].pointLabels();
372 
373  forAll(patchPoints, pointI)
374  {
375  motionPointsMask()[patchPoints[pointI]] = -1;
376  }
377  }
378  }
379 
380  // Mark fixed free surface boundary points
381  for (const word& patchName : fixedFreeSurfacePatches_)
382  {
383  const label fixedPatchID = aMesh().boundary().findPatchID(patchName);
384 
385  if (fixedPatchID == -1)
386  {
388  << "Wrong faPatch name in the fixedFreeSurfacePatches list"
389  << " defined in the dynamicMeshDict dictionary"
390  << abort(FatalError);
391  }
392 
393  const labelList& patchPoints =
394  aMesh().boundary()[fixedPatchID].pointLabels();
395 
396  forAll(patchPoints, pointI)
397  {
398  motionPointsMask()[patchPoints[pointI]] = 0;
399  }
400  }
401 }
402 
403 
404 void Foam::interfaceTrackingFvMesh::makeDirections()
405 {
407  << "make displacement directions for points and control points" << nl;
408 
409  if (pointsDisplacementDirPtr_ || facesDisplacementDirPtr_)
410  {
412  << "points, control points displacement directions already exist"
413  << abort(FatalError);
414  }
415 
416  pointsDisplacementDirPtr_ =
417  new vectorField
418  (
419  mesh().boundaryMesh()[fsPatchIndex()].nPoints(),
420  Zero
421  );
422 
423  facesDisplacementDirPtr_ =
424  new vectorField
425  (
426  mesh().boundaryMesh()[fsPatchIndex()].size(),
427  Zero
428  );
429 
430  if (!normalMotionDir())
431  {
432  if (mag(motionDir_) < SMALL)
433  {
435  << "Zero motion direction"
436  << abort(FatalError);
437  }
438 
439  facesDisplacementDir() = motionDir_;
440  pointsDisplacementDir() = motionDir_;
441  }
442 
443  updateDisplacementDirections();
444 }
445 
446 
447 void Foam::interfaceTrackingFvMesh::makePhis()
448 {
450  << "making free-surface flux" << nl;
451 
452  if (phisPtr_)
453  {
455  << "free-surface flux already exists"
456  << abort(FatalError);
457  }
458 
459  phisPtr_ = new edgeScalarField
460  (
461  IOobject
462  (
463  "phis",
464  mesh().time().timeName(),
465  mesh(),
468  ),
469  linearEdgeInterpolate(Us()) & aMesh().Le()
470  );
471 }
472 
473 
474 void Foam::interfaceTrackingFvMesh::makeSurfactConc() const
475 {
477  << "making free-surface surfactant concentration field" << nl;
478 
479  if (surfactConcPtr_)
480  {
482  << "free-surface surfactant concentration field already exists"
483  << abort(FatalError);
484  }
485 
486  surfactConcPtr_ = new areaScalarField
487  (
488  IOobject
489  (
490  "Cs",
491  mesh().time().timeName
492  (
493  mesh().time().startTime().value()
494  ),
495  // mesh().time().timeName(),
496  mesh(),
499  ),
500  aMesh()
501  );
502 }
503 
504 
505 void Foam::interfaceTrackingFvMesh::makeBulkSurfactConc() const
506 {
508  << "making volume surfactant concentration field" << nl;
509 
510  if (bulkSurfactConcPtr_)
511  {
513  << "volume surfactant concentration field already exists"
514  << abort(FatalError);
515  }
516 
517  bulkSurfactConcPtr_ = new volScalarField
518  (
519  IOobject
520  (
521  "C",
522  mesh().time().timeName
523  (
524  mesh().time().startTime().value()
525  ),
526  // mesh().time().timeName(),
527  mesh(),
530  ),
531  mesh()
532  );
533  volScalarField& bulkSurfactConc = *bulkSurfactConcPtr_;
534 
535  if (mesh().time().timeIndex()-1 == 0)
536  {
537  // Initialize uniform volume surfactant concentration
538  bulkSurfactConc = surfactant().bulkConc();
539  bulkSurfactConc.correctBoundaryConditions();
540  }
541 }
542 
543 
544 void Foam::interfaceTrackingFvMesh::makeSurfaceTension() const
545 {
547  << "making surface tension field" << nl;
548 
549  if (surfaceTensionPtr_)
550  {
552  << "surface tension field already exists"
553  << abort(FatalError);
554  }
555 
556  surfaceTensionPtr_ = new areaScalarField
557  (
558  IOobject
559  (
560  "surfaceTension",
561  mesh().time().timeName(),
562  mesh(),
565  ),
566  sigma() + surfactant().dSigma(surfactantConcentration())/rho_
567  );
568 }
569 
570 
571 void Foam::interfaceTrackingFvMesh::makeSurfactant() const
572 {
574  << "making surfactant properties" << nl;
575 
576  if (surfactantPtr_)
577  {
579  << "surfactant properties already exists"
580  << abort(FatalError);
581  }
582 
583  const dictionary& surfactProp =
584  motion().subDict("surfactantProperties");
585 
586  surfactantPtr_ = new surfactantProperties(surfactProp);
587 }
588 
589 
590 void Foam::interfaceTrackingFvMesh::makeContactAngle()
591 {
593  << "making contact angle field" << nl;
594 
595  if (contactAnglePtr_)
596  {
598  << "contact angle already exists"
599  << abort(FatalError);
600  }
601 
602  // Check if contactAngle is defined
603  IOobject contactAngleHeader
604  (
605  "contactAngle",
606  mesh().time().timeName(),
607  mesh(),
609  );
610 
611  if (contactAngleHeader.typeHeaderOk<areaScalarField>())
612  {
613  Info<< "Reading contact angle field" << endl;
614 
615  contactAnglePtr_ =
616  new areaScalarField
617  (
618  IOobject
619  (
620  "contactAngle",
621  mesh().time().timeName(),
622  mesh(),
625  ),
626  aMesh()
627  );
628  }
629 }
630 
631 
632 void Foam::interfaceTrackingFvMesh::updateDisplacementDirections()
633 {
634  if (normalMotionDir())
635  {
636  // Update point displacement direction
637  pointsDisplacementDir() = aMesh().pointAreaNormals();
638 
639  // Correct point displacement direction at contact line
640  forAll(aMesh().boundary(), patchI)
641  {
642  if (contactAnglePtr_)
643  {
644  label ngbPolyPatchID =
645  aMesh().boundary()[patchI].ngbPolyPatchIndex();
646 
647  if (ngbPolyPatchID != -1)
648  {
649  if
650  (
651  mesh().boundary()[ngbPolyPatchID].type()
652  == wallFvPatch::typeName
653  )
654  {
655  labelList patchPoints =
656  aMesh().boundary()[patchI].pointLabels();
657 
658  vectorField N
659  (
660  aMesh().boundary()[patchI]
661  .ngbPolyPatchPointNormals()
662  );
663 
664  forAll(patchPoints, pointI)
665  {
666  pointsDisplacementDir()[patchPoints[pointI]] -=
667  N[pointI]
668  *(
669  N[pointI]
670  & pointsDisplacementDir()[patchPoints[pointI]]
671  );
672 
673  pointsDisplacementDir()[patchPoints[pointI]] /=
674  mag
675  (
676  pointsDisplacementDir()
677  [
678  patchPoints[pointI]
679  ]
680  ) + SMALL;
681  }
682  }
683  }
684  }
685  }
686 
687  // Update face displacement direction
688  facesDisplacementDir() =
690 
691  // Correction of control points position
692  const vectorField& Cf = aMesh().areaCentres().internalField();
693 
694  controlPoints() =
695  facesDisplacementDir()
696  *(facesDisplacementDir()&(controlPoints() - Cf))
697  + Cf;
698  }
699 }
700 
701 
702 void Foam::interfaceTrackingFvMesh::initializeControlPointsPosition()
703 {
704  {
705  const faceList& faces = aMesh().faces();
706  const pointField& points = aMesh().points();
707 
708  pointField displacement(pointDisplacement());
709  scalarField sweptVolCorr(faces.size(), Zero);
710  correctPointDisplacement(sweptVolCorr, displacement);
711 
712  pointField newPoints(points + displacement);
713 
714  scalarField sweptVol(faces.size(), Zero);
715 
716  forAll(faces, faceI)
717  {
718  sweptVol[faceI] = -faces[faceI].sweptVol(points, newPoints);
719  }
720 
721  vectorField faceArea(faces.size(), Zero);
722 
723  forAll(faceArea, faceI)
724  {
725  faceArea[faceI] = faces[faceI].unitNormal(newPoints);
726  }
727 
728  scalarField deltaH = scalarField(aMesh().nFaces(), Zero);
729 
730  forAll(deltaH, faceI)
731  {
732  deltaH[faceI] = sweptVol[faceI]/
733  ((faceArea[faceI] & facesDisplacementDir()[faceI]) + SMALL);
734 
735  if (mag(faceArea[faceI] & facesDisplacementDir()[faceI]) < SMALL)
736  {
737  // Info<< (faceArea[faceI] & facesDisplacementDir()[faceI])
738  // << ", " << faceArea[faceI]
739  // << ", " << facesDisplacementDir()[faceI] << endl;
740 
741  FatalError
742  << "Something is wrong with specified motion direction"
743  << abort(FatalError);
744  }
745  }
746 
747  for (const word& patchName : fixedFreeSurfacePatches_)
748  {
749  label fixedPatchID = aMesh().boundary().findPatchID(patchName);
750 
751  if (fixedPatchID == -1)
752  {
753  FatalError
754  << "Wrong faPatch name in the fixedFreeSurfacePatches list"
755  << " defined in the freeSurfaceProperties dictionary"
756  << abort(FatalError);
757  }
758 
759  const labelList& eFaces =
760  aMesh().boundary()[fixedPatchID].edgeFaces();
761 
762  forAll(eFaces, edgeI)
763  {
764  deltaH[eFaces[edgeI]] *= 2.0;
765  }
766  }
767 
768  controlPoints() += facesDisplacementDir()*deltaH;
769  }
770 }
771 
772 
773 void Foam::interfaceTrackingFvMesh::smoothFreeSurfaceMesh()
774 {
775  Info<< "Smoothing free surface mesh" << endl;
776 
777  controlPoints() = aMesh().areaCentres().internalField();
778 
779  pointField displacement(pointDisplacement());
780 
781  const faceList& faces = aMesh().faces();
782  const pointField& points = aMesh().points();
783 
784  pointField newPoints(points + displacement);
785 
786  scalarField sweptVol(faces.size(), Zero);
787  forAll(faces, faceI)
788  {
789  sweptVol[faceI] = -faces[faceI].sweptVol(points, newPoints);
790  }
791 
792  vectorField faceArea(faces.size(), Zero);
793  forAll(faceArea, faceI)
794  {
795  faceArea[faceI] = faces[faceI].unitNormal(newPoints);
796  }
797 
798  scalarField deltaHf
799  (
800  sweptVol/(faceArea & facesDisplacementDir())
801  );
802 
803  for (const word& patchName : fixedFreeSurfacePatches_)
804  {
805  label fixedPatchID = aMesh().boundary().findPatchID(patchName);
806 
807  if (fixedPatchID == -1)
808  {
809  FatalError
810  << "Wrong faPatch name fixedFreeSurfacePatches list"
811  << " defined in the dynamicMeshDict dictionary"
812  << abort(FatalError);
813  }
814 
815  const labelList& eFaces =
816  aMesh().boundary()[fixedPatchID].edgeFaces();
817 
818  forAll(eFaces, edgeI)
819  {
820  deltaHf[eFaces[edgeI]] *= 2.0;
821  }
822  }
823 
824  controlPoints() += facesDisplacementDir()*deltaHf;
825 
826  displacement = pointDisplacement();
827 
828  velocityMotionSolver& vMotion =
829  refCast<velocityMotionSolver>
830  (
831  const_cast<motionSolver&>(motion())
832  );
833 
834  pointVectorField& pointMotionU = vMotion.pointMotionU();
835  pointMotionU.primitiveFieldRef() = Zero;
836 
837  fixedValuePointPatchVectorField& fsPatchPointMeshU =
838  refCast<fixedValuePointPatchVectorField>
839  (
840  const_cast<pointPatchVectorField&>
841  (
842  pointMotionU.boundaryField()[fsPatchIndex()]
843  )
844  );
845 
846  fsPatchPointMeshU ==
847  displacement/mesh().time().deltaT().value();
848 
850 }
851 
852 
853 void Foam::interfaceTrackingFvMesh::updateSurfaceFlux()
854 {
855  Phis() = fac::interpolate(Us()) & aMesh().Le();
856 }
857 
858 
859 void Foam::interfaceTrackingFvMesh::updateSurfactantConcentration()
860 {
861  if (!pureFreeSurface())
862  {
863  Info<< "Correct surfactant concentration" << endl << flush;
864 
865  updateSurfaceFlux();
866 
867  // Crate and solve the surfactanta transport equation
868  faScalarMatrix CsEqn
869  (
870  fam::ddt(surfactantConcentration())
871  + fam::div(Phis(), surfactantConcentration())
873  (
874  surfactant().diffusion(),
875  surfactantConcentration()
876  )
877  );
878 
879  if (surfactant().soluble())
880  {
881  #include "solveBulkSurfactant.H"
882 
884  (
885  IOobject
886  (
887  "Cb",
888  mesh().time().timeName(),
889  mesh(),
892  ),
893  aMesh(),
895  zeroGradientFaPatchScalarField::typeName
896  );
897 
898  Cb.ref().field() =
899  bulkSurfactantConcentration().boundaryField()[fsPatchIndex()];
900  Cb.correctBoundaryConditions();
901 
902  CsEqn +=
903  fam::Sp
904  (
905  surfactant().adsorptionCoeff()*Cb
906  + surfactant().adsorptionCoeff()
907  *surfactant().desorptionCoeff(),
908  surfactantConcentration()
909  )
910  - surfactant().adsorptionCoeff()
911  *Cb*surfactant().saturatedConc();
912  }
913 
914  CsEqn.solve();
915 
916  // Info<< "Correct surface tension" << endl;
917 
918  surfaceTension() =
919  sigma() + surfactant().dSigma(surfactantConcentration())/rho_;
920 
921  if (neg(min(surfaceTension().internalField().field())))
922  {
924  << "Surface tension is negative"
925  << abort(FatalError);
926  }
927  }
928 }
929 
930 
931 Foam::vector Foam::interfaceTrackingFvMesh::totalPressureForce() const
932 {
933  const scalarField& S = aMesh().S();
934 
936 
937  const scalarField& P = p().boundaryField()[fsPatchIndex()];
938 
939  vectorField pressureForces(S*P*n);
940 
941  return gSum(pressureForces);
942 }
943 
944 
945 Foam::vector Foam::interfaceTrackingFvMesh::totalViscousForce() const
946 {
947  const auto& turbulence =
948  mesh().lookupObject<turbulenceModel>("turbulenceProperties");
949 
950  scalarField nu(turbulence.nuEff(fsPatchIndex()));
951 
952  // const singlePhaseTransportModel& properties =
953  // mesh().lookupObject<singlePhaseTransportModel>
954  // (
955  // "transportProperties"
956  // );
957 
958  // dimensionedScalar nu("nu", properties);
959 
960  const scalarField& S = aMesh().S();
962 
963  vectorField nGradU
964  (
965  U().boundaryField()[fsPatchIndex()].snGrad()
966  );
967 
968  vectorField viscousForces
969  (
970  - nu*S
971  *(
972  nGradU
973  + (fac::grad(Us())().internalField()&n)
974  - (n*fac::div(Us())().internalField())
975  )
976  );
977 
978  return gSum(viscousForces);
979 }
980 
981 
982 Foam::vector Foam::interfaceTrackingFvMesh::totalSurfaceTensionForce() const
983 {
984  const scalarField& S = aMesh().S();
985 
987 
989 
990  vectorField surfTensionForces(n.size(), Zero);
991 
992  if (pureFreeSurface())
993  {
994  surfTensionForces =
995  S*sigma().value()
997  (
998  aMesh().Le()*aMesh().edgeLengthCorrection()
999  )().internalField();
1000  }
1001  else
1002  {
1003  surfTensionForces = surfaceTension().internalField().field()*K*S*n;
1004  }
1005 
1006  return gSum(surfTensionForces);
1007 }
1008 
1009 
1010 Foam::scalar Foam::interfaceTrackingFvMesh::maxCourantNumber()
1011 {
1012  scalar CoNum = 0;
1013 
1014  if (pureFreeSurface())
1015  {
1016  const scalarField& dE = aMesh().lPN();
1017 
1018  CoNum = gMax
1019  (
1020  mesh().time().deltaT().value()/
1021  sqrt
1022  (
1023  Foam::pow(dE, 3.0)/2.0/M_PI/(sigma().value() + SMALL)
1024  )
1025  );
1026  }
1027  else
1028  {
1029  scalarField sigmaE
1030  (
1031  linearEdgeInterpolate(surfaceTension())().internalField().field()
1032  + SMALL
1033  );
1034 
1035  const scalarField& dE = aMesh().lPN();
1036 
1037  CoNum = gMax
1038  (
1039  mesh().time().deltaT().value()/
1040  sqrt
1041  (
1042  Foam::pow(dE, 3.0)/2.0/M_PI/sigmaE
1043  )
1044  );
1045  }
1046 
1047  return CoNum;
1048 }
1049 
1050 
1051 void Foam::interfaceTrackingFvMesh::updateProperties()
1052 {
1053  const singlePhaseTransportModel& properties =
1055  (
1056  "transportProperties"
1057  );
1058 
1059  rho_ = dimensionedScalar("rho", properties);
1060 
1061  sigma0_ = dimensionedScalar("sigma", properties)/rho_;
1062 }
1063 
1064 
1065 void Foam::interfaceTrackingFvMesh::correctPointDisplacement
1066 (
1067  const scalarField& sweptVolCorr,
1068  vectorField& displacement
1069 )
1070 {
1071  const labelListList& pFaces =
1072  aMesh().patch().pointFaces();
1073 
1074  const faceList& faces =
1075  aMesh().patch().localFaces();
1076 
1077  const pointField& points =
1078  aMesh().patch().localPoints();
1079 
1080  for (const word& patchName : fixedFreeSurfacePatches_)
1081  {
1082  label fixedPatchID = aMesh().boundary().findPatchID(patchName);
1083 
1084  const labelList& pLabels =
1085  aMesh().boundary()[fixedPatchID].pointLabels();
1086 
1087  const labelList& eFaces =
1088  aMesh().boundary()[fixedPatchID].edgeFaces();
1089 
1091 
1092  forAll(eFaces, edgeI)
1093  {
1094  label curFace = eFaces[edgeI];
1095 
1096  const labelList& curPoints = faces[curFace];
1097 
1098  forAll(curPoints, pointI)
1099  {
1100  label curPoint = curPoints[pointI];
1101  label index = pLabels.find(curPoint);
1102 
1103  if (index == -1)
1104  {
1105  pointSet.insert(curPoint);
1106  }
1107  }
1108  }
1109 
1110  labelList corrPoints = pointSet.toc();
1111 
1112  labelListList corrPointFaces(corrPoints.size());
1113 
1114  forAll(corrPoints, pointI)
1115  {
1116  label curPoint = corrPoints[pointI];
1117 
1119 
1120  forAll(pFaces[curPoint], faceI)
1121  {
1122  label curFace = pFaces[curPoint][faceI];
1123 
1124  label index = eFaces.find(curFace);
1125 
1126  if (index != -1)
1127  {
1128  faceSet.insert(curFace);
1129  }
1130  }
1131 
1132  corrPointFaces[pointI] = faceSet.toc();
1133  }
1134 
1135  forAll(corrPoints, pointI)
1136  {
1137  label curPoint = corrPoints[pointI];
1138 
1139  scalar curDisp = 0;
1140 
1141  const labelList& curPointFaces = corrPointFaces[pointI];
1142 
1143  forAll(curPointFaces, faceI)
1144  {
1145  const face& curFace = faces[curPointFaces[faceI]];
1146 
1147  label ptInFace = curFace.which(curPoint);
1148  label next = curFace.nextLabel(ptInFace);
1149  label prev = curFace.prevLabel(ptInFace);
1150 
1151  vector a = points[next] - points[curPoint];
1152  vector b = points[prev] - points[curPoint];
1153  const vector& c = pointsDisplacementDir()[curPoint];
1154 
1155  curDisp += 2*sweptVolCorr[curPointFaces[faceI]]/((a^b)&c);
1156  }
1157 
1158  curDisp /= curPointFaces.size();
1159 
1160  displacement[curPoint] =
1161  curDisp*pointsDisplacementDir()[curPoint];
1162  }
1163  }
1164 
1165 
1166  for (const word& patchName : nonReflectingFreeSurfacePatches_)
1167  {
1168  label nonReflectingPatchID =
1169  aMesh().boundary().findPatchID(patchName);
1170 
1171  const labelList& pLabels =
1172  aMesh().boundary()[nonReflectingPatchID].pointLabels();
1173 
1174  const labelList& eFaces =
1175  aMesh().boundary()[nonReflectingPatchID].edgeFaces();
1176 
1177  labelList corrPoints = pLabels;
1178 
1179  labelListList corrPointFaces(corrPoints.size());
1180 
1181  forAll(corrPoints, pointI)
1182  {
1183  label curPoint = corrPoints[pointI];
1184 
1186 
1187  forAll(pFaces[curPoint], faceI)
1188  {
1189  label curFace = pFaces[curPoint][faceI];
1190 
1191  label index = eFaces.find(curFace);
1192 
1193  if (index != -1)
1194  {
1195  faceSet.insert(curFace);
1196  }
1197  }
1198 
1199  corrPointFaces[pointI] = faceSet.toc();
1200  }
1201 
1202 
1203  forAll(corrPoints, pointI)
1204  {
1205  label curPoint = corrPoints[pointI];
1206 
1207  scalar curDisp = 0;
1208 
1209  const labelList& curPointFaces = corrPointFaces[pointI];
1210 
1211  forAll(curPointFaces, faceI)
1212  {
1213  const face& curFace = faces[curPointFaces[faceI]];
1214 
1215  label ptInFace = curFace.which(curPoint);
1216  label next = curFace.nextLabel(ptInFace);
1217  label prev = curFace.prevLabel(ptInFace);
1218 
1219  label p0 = -1;
1220  label p1 = -1;
1221  label p2 = -1;
1222 
1223  if (corrPoints.find(next) == -1)
1224  {
1225  p0 = curPoint;
1226  p1 = next;
1227  p2 = curFace.nextLabel(curFace.which(next));
1228  }
1229  else
1230  {
1231  p0 = curFace.prevLabel(curFace.which(prev));
1232  p1 = prev;
1233  p2 = curPoint;
1234  }
1235 
1236  vector a0 = points[p1] - points[p0];
1237  vector b0 = points[p2] - points[p1];
1238  vector c0 = displacement[p1];
1239 
1240  scalar V0 = mag((a0^b0)&c0)/2;
1241 
1242  scalar DV = sweptVolCorr[curPointFaces[faceI]] - V0;
1243 
1244  if (corrPoints.find(prev) != -1)
1245  {
1246  vector a = points[curPoint] - points[prev];
1247  vector b =
1248  (points[next] + displacement[next])
1249  - points[curPoint];
1250  const vector& c = pointsDisplacementDir()[curPoint];
1251 
1252  curDisp += 2*DV/((a^b)&c);
1253  }
1254  else
1255  {
1256  vector a = points[curPoint]
1257  - (points[prev] + displacement[prev]);
1258  vector b = points[next] - points[curPoint];
1259  const vector& c = pointsDisplacementDir()[curPoint];
1260 
1261  curDisp += 2*DV/((a^b)&c);
1262  }
1263  }
1264 
1265  curDisp /= curPointFaces.size();
1266 
1267  displacement[curPoint] =
1268  curDisp*pointsDisplacementDir()[curPoint];
1269  }
1270  }
1271 }
1272 
1273 
1274 void Foam::interfaceTrackingFvMesh::correctContactLinePointNormals()
1275 {
1276  // Correct normals for contact line points
1277  // according to specified contact angle
1278 
1279  vectorField& N =
1280  const_cast<vectorField&>
1281  (
1283  );
1284 
1285  if (contactAnglePtr_ && correctContactLineNormals())
1286  {
1287  Info<< "Correcting contact line normals" << endl;
1288 
1289  vectorField oldPoints(aMesh().nPoints(), Zero);
1290 
1291  const labelList& meshPoints = aMesh().patch().meshPoints();
1292 
1293  forAll(oldPoints, ptI)
1294  {
1295  oldPoints[ptI] =
1296  mesh().oldPoints()[meshPoints[ptI]];
1297  }
1298 
1299 // # include "createTangentField.H"
1300  areaVectorField tangent
1301  (
1302  IOobject
1303  (
1304  "tangent",
1305  mesh().time().timeName(),
1306  mesh(),
1309  ),
1310  aMesh(),
1312  );
1313 
1314  if (Pstream::parRun())
1315  {
1316  const labelListList& edgeFaces = aMesh().patch().edgeFaces();
1317  const labelListList& pointEdges = aMesh().patch().pointEdges();
1318  const labelListList& pointFaces = aMesh().patch().pointFaces();
1319  const edgeList& edges = aMesh().edges();
1320 
1321  forAll(aMesh().boundary(), patchI)
1322  {
1323  if
1324  (
1325  aMesh().boundary()[patchI].type()
1326  == processorFaPatch::typeName
1327  )
1328  {
1329  const processorFaPatch& procPatch =
1330  refCast<const processorFaPatch>
1331  (
1332  aMesh().boundary()[patchI]
1333  );
1334 
1335  const labelList& patchPointLabels =
1336  procPatch.pointLabels();
1337 
1338  forAll(patchPointLabels, pointI)
1339  {
1340  label curPoint = patchPointLabels[pointI];
1341 
1342  // Check if processor point is boundary point
1343 
1344  label patchID = -1;
1345  label edgeID = -1;
1346 
1347  const labelList& curPointEdges = pointEdges[curPoint];
1348 
1349  forAll(curPointEdges, edgeI)
1350  {
1351  label curEdge = curPointEdges[edgeI];
1352 
1353  if (edgeFaces[curEdge].size() == 1)
1354  {
1355  forAll(aMesh().boundary(), pI)
1356  {
1357  const labelList& curEdges =
1358  aMesh().boundary()[pI];
1359 
1360  label index = curEdges.find(curEdge);
1361 
1362  if (index != -1)
1363  {
1364  if
1365  (
1366  aMesh().boundary()[pI].type()
1367  != processorFaPatch::typeName
1368  )
1369  {
1370  patchID = pI;
1371  edgeID = index;
1372  break;
1373  }
1374  }
1375  }
1376  }
1377  }
1378 
1379  if (patchID != -1)
1380  {
1381  label curEdge =
1382  aMesh().boundary()[patchID].start() + edgeID;
1383 
1384  vector t = edges[curEdge].vec(oldPoints);
1385  t /= mag(t) + SMALL;
1386 
1387  const labelList& curPointFaces =
1388  pointFaces[curPoint];
1389 
1390  forAll(curPointFaces, fI)
1391  {
1392  tangent.ref().field()[curPointFaces[fI]] = t;
1393  }
1394  }
1395  }
1396  }
1397  }
1398 
1399  tangent.correctBoundaryConditions();
1400  }
1401 
1402  forAll(aMesh().boundary(), patchI)
1403  {
1404  label ngbPolyPatchID =
1405  aMesh().boundary()[patchI].ngbPolyPatchIndex();
1406 
1407  if (ngbPolyPatchID != -1)
1408  {
1409  if
1410  (
1411  mesh().boundary()[ngbPolyPatchID].type()
1412  == wallFvPatch::typeName
1413  )
1414  {
1415  const scalar rotAngle = degToRad
1416  (
1417  gAverage
1418  (
1419  90
1420  - contactAnglePtr_->boundaryField()[patchI]
1421  )
1422  );
1423 
1424  vectorField ngbN
1425  (
1426  aMesh().boundary()[patchI].ngbPolyPatchPointNormals()
1427  );
1428 
1429  const labelList& patchPoints =
1430  aMesh().boundary()[patchI].pointLabels();
1431 
1432  vectorField pN(N, patchPoints);
1433 
1434  vectorField rotationAxis(ngbN^pN);
1435  rotationAxis /= mag(rotationAxis) + SMALL;
1436 
1437 
1438  // Calc rotation axis using edge vectors
1439 
1440  const edgeList& edges = aMesh().edges();
1441 
1442  const labelListList& pointEdges =
1443  aMesh().boundary()[patchI].pointEdges();
1444 
1445  forAll(pointEdges, pointI)
1446  {
1447  vector rotAx = Zero;
1448 
1449  forAll(pointEdges[pointI], eI)
1450  {
1451  label curEdge =
1452  aMesh().boundary()[patchI].start()
1453  + pointEdges[pointI][eI];
1454 
1455  vector e = edges[curEdge].vec(oldPoints);
1456 
1457  e *= (e&rotationAxis[pointI])
1458  /mag(e&rotationAxis[pointI]);
1459 
1460  e /= mag(e) + SMALL;
1461 
1462  rotAx += e;
1463  }
1464 
1465  if (pointEdges[pointI].size() == 1)
1466  {
1467  label curPoint = patchPoints[pointI];
1468 
1469  const labelListList& ptEdges =
1470  aMesh().patch().pointEdges();
1471  const labelList& curPointEdges =
1472  ptEdges[curPoint];
1473 
1474  label procPatchID = -1;
1475  label edgeID = -1;
1476 
1477  const labelListList& edgeFaces =
1478  aMesh().patch().edgeFaces();
1479 
1480  forAll(curPointEdges, edgeI)
1481  {
1482  label curEdge = curPointEdges[edgeI];
1483 
1484  if (edgeFaces[curEdge].size() == 1)
1485  {
1486  forAll(aMesh().boundary(), pI)
1487  {
1488  const labelList& curEdges =
1489  aMesh().boundary()[pI];
1490 
1491  label index =
1492  curEdges.find(curEdge);
1493 
1494  if (index != -1)
1495  {
1496  if
1497  (
1498  aMesh().boundary()[pI].type()
1499  == processorFaPatch::typeName
1500  )
1501  {
1502  procPatchID = pI;
1503  edgeID = index;
1504  break;
1505  }
1506  }
1507  }
1508  }
1509  }
1510 
1511  if (procPatchID != -1)
1512  {
1513  vector t =
1514  tangent.boundaryField()[procPatchID]
1515  .patchNeighbourField()()[edgeID];
1516 
1517  t *= (t&rotationAxis[pointI])
1518  /(mag(t&rotationAxis[pointI]) + SMALL);
1519 
1520  t /= mag(t) + SMALL;
1521 
1522  rotAx += t;
1523  }
1524  }
1525 
1526  rotationAxis[pointI] = rotAx/(mag(rotAx) + SMALL);
1527  }
1528 
1529  // Rodrigues' rotation formula
1530  ngbN = ngbN*cos(rotAngle)
1531  + rotationAxis*(rotationAxis & ngbN)*(1 - cos(rotAngle))
1532  + (rotationAxis^ngbN)*sin(rotAngle);
1533 
1534  // Info<< aMesh().boundary()[patchI].name() << endl;
1535  forAll(patchPoints, pointI)
1536  {
1537  N[patchPoints[pointI]] -=
1538  ngbN[pointI]*(ngbN[pointI]&N[patchPoints[pointI]]);
1539 
1540  N[patchPoints[pointI]] /=
1541  mag(N[patchPoints[pointI]]) + SMALL;
1542 
1543  // Info<< N[patchPoints[pointI]] << endl;
1544  }
1545  }
1546  }
1547  }
1548  }
1549 }
1550 
1551 
1552 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1553 
1554 Foam::interfaceTrackingFvMesh::interfaceTrackingFvMesh
1556  const IOobject& io,
1557  const bool doInit
1558 )
1559 :
1560  dynamicMotionSolverFvMesh(io, doInit),
1561  aMeshPtr_(nullptr),
1562  fsPatchIndex_(-1),
1563  fixedFreeSurfacePatches_(),
1564  nonReflectingFreeSurfacePatches_(),
1565  pointNormalsCorrectionPatches_(),
1566  normalMotionDir_(false),
1567  motionDir_(Zero),
1568  smoothing_(false),
1569  pureFreeSurface_(true),
1570  rigidFreeSurface_(false),
1571  correctContactLineNormals_(false),
1572  sigma0_("zero", dimForce/dimLength/dimDensity, Zero),
1573  rho_("one", dimDensity, 1.0),
1574  timeIndex_(-1),
1575  UsPtr_(nullptr),
1576  controlPointsPtr_(nullptr),
1577  motionPointsMaskPtr_(nullptr),
1578  pointsDisplacementDirPtr_(nullptr),
1579  facesDisplacementDirPtr_(nullptr),
1580  fsNetPhiPtr_(nullptr),
1581  phisPtr_(nullptr),
1582  surfactConcPtr_(nullptr),
1583  bulkSurfactConcPtr_(nullptr),
1584  surfaceTensionPtr_(nullptr),
1585  surfactantPtr_(nullptr),
1586  contactAnglePtr_(nullptr)
1587 {
1588  if (doInit)
1589  {
1590  init(false); // do not initialise lower levels
1591  }
1592 }
1593 
1594 /*
1595 Foam::interfaceTrackingFvMesh::interfaceTrackingFvMesh
1596 (
1597  const IOobject& io,
1598  pointField&& points,
1599  faceList&& faces,
1600  labelList&& allOwner,
1601  labelList&& allNeighbour,
1602  const bool syncPar
1603 )
1604 :
1605  dynamicMotionSolverFvMesh
1606  (
1607  io,
1608  std::move(points),
1609  std::move(faces),
1610  std::move(allOwner),
1611  std::move(allNeighbour),
1612  syncPar
1613  ),
1614  aMeshPtr_(new faMesh(*this)),
1615  fsPatchIndex_(-1),
1616  fixedFreeSurfacePatches_(),
1617  nonReflectingFreeSurfacePatches_(),
1618  pointNormalsCorrectionPatches_(),
1619  normalMotionDir_(false),
1620  motionDir_(Zero),
1621  smoothing_(false),
1622  pureFreeSurface_(true),
1623  sigma0_("zero", dimForce/dimLength/dimDensity, Zero),
1624  rho_("one", dimDensity, 1.0),
1625  timeIndex_(-1),
1626  UsPtr_(nullptr),
1627  controlPointsPtr_(nullptr),
1628  motionPointsMaskPtr_(nullptr),
1629  pointsDisplacementDirPtr_(nullptr),
1630  facesDisplacementDirPtr_(nullptr),
1631  fsNetPhiPtr_(nullptr),
1632  phisPtr_(nullptr),
1633  surfactConcPtr_(nullptr),
1634  bulkSurfactConcPtr_(nullptr),
1635  surfaceTensionPtr_(nullptr),
1636  surfactantPtr_(nullptr),
1637  contactAnglePtr_(nullptr)
1638 {}
1639 */
1640 
1641 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1642 
1644 {
1645  deleteDemandDrivenData(UsPtr_);
1646  deleteDemandDrivenData(controlPointsPtr_);
1647  deleteDemandDrivenData(motionPointsMaskPtr_);
1648  deleteDemandDrivenData(pointsDisplacementDirPtr_);
1649  deleteDemandDrivenData(facesDisplacementDirPtr_);
1650  deleteDemandDrivenData(fsNetPhiPtr_);
1651  deleteDemandDrivenData(phisPtr_);
1652  deleteDemandDrivenData(surfactConcPtr_);
1653  deleteDemandDrivenData(bulkSurfactConcPtr_);
1654  deleteDemandDrivenData(surfaceTensionPtr_);
1655  deleteDemandDrivenData(surfactantPtr_);
1656  deleteDemandDrivenData(contactAnglePtr_);
1657 }
1658 
1659 
1660 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1661 
1663 {
1664  if (doInit)
1665  {
1667  }
1668 
1669  aMeshPtr_.reset(new faMesh(*this));
1670 
1671  // Set motion-based data
1672  fixedFreeSurfacePatches_ =
1673  motion().get<wordList>("fixedFreeSurfacePatches");
1674 
1675  pointNormalsCorrectionPatches_ =
1676  motion().get<wordList>("pointNormalsCorrectionPatches");
1677 
1678  normalMotionDir_ = motion().get<bool>("normalMotionDir");
1679  smoothing_ = motion().getOrDefault("smoothing", false);
1680  pureFreeSurface_ = motion().getOrDefault("pureFreeSurface", true);
1681 
1682  initializeData();
1683 
1684  return true;
1685 }
1686 
1687 
1689 {
1690  if (!UsPtr_)
1691  {
1692  makeUs();
1693  }
1694 
1695  return *UsPtr_;
1696 }
1697 
1698 
1700 {
1701  if (!UsPtr_)
1702  {
1703  makeUs();
1704  }
1705 
1706  return *UsPtr_;
1707 }
1708 
1709 
1711 {
1712  if (!fsNetPhiPtr_)
1713  {
1714  makeFsNetPhi();
1715  }
1716 
1717  return *fsNetPhiPtr_;
1718 }
1719 
1720 
1722 {
1723  if (!fsNetPhiPtr_)
1724  {
1725  makeFsNetPhi();
1726  }
1727 
1728  return *fsNetPhiPtr_;
1729 }
1730 
1731 
1733 {
1734  forAll(Us().boundaryField(), patchI)
1735  {
1736  if
1737  (
1738  Us().boundaryField()[patchI].type()
1739  == calculatedFaPatchVectorField::typeName
1740  )
1741  {
1742  vectorField& pUs = Us().boundaryFieldRef()[patchI];
1743 
1744  pUs = Us().boundaryField()[patchI].patchInternalField();
1745 
1746  label ngbPolyPatchID =
1747  aMesh().boundary()[patchI].ngbPolyPatchIndex();
1748 
1749  if (ngbPolyPatchID != -1)
1750  {
1751  if
1752  (
1753  (
1754  U().boundaryField()[ngbPolyPatchID].type()
1755  == slipFvPatchVectorField::typeName
1756  )
1757  ||
1758  (
1759  U().boundaryField()[ngbPolyPatchID].type()
1760  == symmetryFvPatchVectorField::typeName
1761  )
1762  )
1763  {
1764  vectorField N
1765  (
1766  aMesh().boundary()[patchI].ngbPolyPatchFaceNormals()
1767  );
1768 
1769  pUs -= N*(N&pUs);
1770  }
1771  }
1772  }
1773  }
1774 
1775  Us().correctBoundaryConditions();
1776 }
1777 
1778 
1780 {
1781  // Info<< "Update Us" << endl;
1782 
1783  Us().ref().field() = U().boundaryField()[fsPatchIndex()];
1784 
1785  // // Correct normal component of free-surface velocity
1786  // const vectorField& nA = aMesh().faceAreaNormals().internalField();
1787  // vectorField UnFs = nA*phi().boundaryField()[fsPatchIndex()]
1788  // /mesh().boundary()[fsPatchIndex()].magSf();
1789  // Us().ref().field() += UnFs - nA*(nA&Us().internalField());
1790 
1791  correctUsBoundaryConditions();
1792 }
1793 
1794 
1796 {
1797  return *getObjectPtr<const volVectorField>("U");
1798 }
1799 
1800 
1802 {
1803  return *getObjectPtr<const volScalarField>("p");
1804 }
1805 
1806 
1808 {
1809  return *getObjectPtr<const surfaceScalarField>("phi");
1810 }
1811 
1812 
1815 {
1816  auto tSnGradU = tmp<vectorField>::New(aMesh().nFaces(), Zero);
1817  auto& SnGradU = tSnGradU.ref();
1818 
1819  const vectorField& nA = aMesh().faceAreaNormals().internalField();
1820 
1821  areaScalarField divUs
1822  (
1823  fac::div(Us())
1824  - aMesh().faceCurvatures()*(aMesh().faceAreaNormals()&Us())
1825  );
1826 
1827  areaTensorField gradUs(fac::grad(Us()));
1828 
1829  // Remove component of gradient normal to surface (area)
1830  const areaVectorField& n = aMesh().faceAreaNormals();
1831  gradUs -= n*(n & gradUs);
1832  gradUs.correctBoundaryConditions();
1833 
1834  const turbulenceModel& turbulence =
1835  mesh().lookupObject<turbulenceModel>("turbulenceProperties");
1836 
1837  scalarField nu(turbulence.nuEff(fsPatchIndex()));
1838 
1839  vectorField tangentialSurfaceTensionForce(nA.size(), Zero);
1840 
1841  if (!pureFreeSurface() && max(nu) > SMALL)
1842  {
1843  tangentialSurfaceTensionForce =
1844  surfaceTensionGrad()().internalField();
1845  }
1846 
1847  SnGradU =
1848  tangentialSurfaceTensionForce/(nu + SMALL)
1849  - nA*divUs.internalField()
1850  - (gradUs.internalField()&nA);
1851 
1852  return tSnGradU;
1853 }
1854 
1855 
1858 {
1859  auto tSnGradUn = tmp<scalarField>::New(aMesh().nFaces(), Zero);
1860  auto& SnGradUn = tSnGradUn.ref();
1861 
1862  areaScalarField divUs
1863  (
1864  fac::div(Us())
1865  - aMesh().faceCurvatures()*(aMesh().faceAreaNormals()&Us())
1866  );
1867 
1868  SnGradUn = -divUs.internalField();
1869 
1870  return tSnGradUn;
1871 }
1872 
1873 
1876 {
1877  auto tPressureJump = tmp<scalarField>::New(aMesh().nFaces(), Zero);
1878  auto& pressureJump = tPressureJump.ref();
1879 
1881 
1883  meshObjects::gravity::New(mesh().time());
1884 
1885  const turbulenceModel& turbulence =
1886  mesh().lookupObject<turbulenceModel>("turbulenceProperties");
1887 
1888  scalarField nu(turbulence.nuEff(fsPatchIndex()));
1889 
1890  pressureJump =
1891  - (g.value() & mesh().Cf().boundaryField()[fsPatchIndex()])
1892  + 2.0*nu*freeSurfaceSnGradUn();
1893 
1894  if (pureFreeSurface())
1895  {
1896  pressureJump -= sigma().value()*K;
1897  }
1898  else
1899  {
1900  pressureJump -= surfaceTension().internalField()*K;
1901  }
1902 
1903  return tPressureJump;
1904 }
1905 
1906 
1908 {
1909  if (!controlPointsPtr_)
1910  {
1911  makeControlPoints();
1912  }
1913 
1914  return *controlPointsPtr_;
1915 }
1916 
1917 
1919 {
1920  if (!motionPointsMaskPtr_)
1921  {
1922  makeMotionPointsMask();
1923  }
1924 
1925  return *motionPointsMaskPtr_;
1926 }
1927 
1928 
1930 {
1931  if (!pointsDisplacementDirPtr_)
1932  {
1933  makeDirections();
1934  }
1935 
1936  return *pointsDisplacementDirPtr_;
1937 }
1938 
1939 
1941 {
1942  if (!facesDisplacementDirPtr_)
1943  {
1944  makeDirections();
1945  }
1946 
1947  return *facesDisplacementDirPtr_;
1948 }
1949 
1950 
1952 {
1953  if (!phisPtr_)
1954  {
1955  makePhis();
1956  }
1957 
1958  return *phisPtr_;
1959 }
1960 
1963 {
1964  if (!surfactConcPtr_)
1965  {
1966  makeSurfactConc();
1967  }
1968 
1969  return *surfactConcPtr_;
1970 }
1971 
1972 
1973 const Foam::areaScalarField&
1975 {
1976  if (!surfactConcPtr_)
1977  {
1978  makeSurfactConc();
1979  }
1980 
1981  return *surfactConcPtr_;
1982 }
1983 
1984 
1987 {
1988  if (!bulkSurfactConcPtr_)
1989  {
1990  makeBulkSurfactConc();
1991  }
1992 
1993  return *bulkSurfactConcPtr_;
1994 }
1995 
1996 
1997 const Foam::volScalarField&
1999 {
2000  if (!bulkSurfactConcPtr_)
2001  {
2002  makeBulkSurfactConc();
2003  }
2004 
2005  return *bulkSurfactConcPtr_;
2006 }
2007 
2008 
2011 {
2012  if (!surfaceTensionPtr_)
2013  {
2014  makeSurfaceTension();
2015  }
2016 
2017  return *surfaceTensionPtr_;
2018 }
2019 
2020 
2021 const Foam::areaScalarField&
2023 {
2024  if (!surfaceTensionPtr_)
2025  {
2026  makeSurfaceTension();
2027  }
2028 
2029  return *surfaceTensionPtr_;
2030 }
2031 
2032 
2035 {
2036  if (!surfactantPtr_)
2037  {
2038  makeSurfactant();
2039  }
2040 
2041  return *surfactantPtr_;
2042 }
2043 
2044 
2047 {
2048  auto tgrad = tmp<areaVectorField>::New
2049  (
2050  IOobject
2051  (
2052  "surfaceTensionGrad",
2053  mesh().time().timeName(),
2054  mesh(),
2057  ),
2058  fac::grad(surfaceTension())
2059  // (-fac::grad(surfactantConcentration()/rho_)*
2060  // surfactant().surfactR()*surfactant().surfactT()/
2061  // (1.0 - surfactantConcentration()/
2062  // surfactant().surfactSaturatedConc()))()
2063  );
2064  auto& grad = tgrad.ref();
2065 
2066  // Remove component of gradient normal to surface (area)
2067  const areaVectorField& n = aMesh().faceAreaNormals();
2068  grad -= n*(n & grad);
2069  grad.correctBoundaryConditions();
2070 
2071  return tgrad;
2072 }
2073 
2074 
2076 {
2077  if (timeIndex_ != mesh().time().timeIndex())
2078  {
2079  if (smoothing_ && !rigidFreeSurface_)
2080  {
2081  smoothFreeSurfaceMesh();
2082  clearControlPoints();
2083  }
2084 
2085  updateDisplacementDirections();
2086 
2087  updateProperties();
2088 
2089  Info<< "Maximal capillary Courant number: "
2090  << maxCourantNumber() << endl;
2091 
2093 
2094  Info<< "Free surface curvature: min = " << gMin(K)
2095  << ", max = " << gMax(K) << ", average = " << gAverage(K) << nl;
2096 
2097  timeIndex_ = mesh().time().timeIndex();
2098  }
2099 
2100  if (!rigidFreeSurface_)
2101  {
2102  // This is currently relaltive flux
2103  scalarField sweptVolCorr =
2104  phi().boundaryField()[fsPatchIndex()];
2105 
2106  // Info<< "Free surface flux: sum local = "
2107  // << gSum(mag(sweptVolCorr))
2108  // << ", global = " << gSum(sweptVolCorr) << endl;
2109 
2110  // if (mesh().moving())
2111  // {
2112  // sweptVolCorr -=
2113  // fvc::meshPhi(U())().boundaryField()[fsPatchIndex()];
2114  // }
2115 
2116  Info<< "Free surface continuity error : sum local = "
2117  << gSum(mag(sweptVolCorr)) << ", global = " << gSum(sweptVolCorr)
2118  << endl;
2119 
2120  // For postprocessing
2121  fsNetPhi().ref().field() = sweptVolCorr;
2122 
2123  word ddtScheme
2124  (
2125  mesh().ddtScheme
2126  (
2127  "ddt(" + U().name() + ')'
2128  )
2129  );
2130 
2131  if
2132  (
2133  ddtScheme
2135  )
2136  {
2137  sweptVolCorr *= (1.0/2.0)*mesh().time().deltaT().value();
2138  }
2139  else if
2140  (
2141  ddtScheme
2143  )
2144  {
2145  sweptVolCorr *= mesh().time().deltaT().value();
2146  }
2147  else if
2148  (
2149  ddtScheme
2151  )
2152  {
2153  if (mesh().time().timeIndex() == 1)
2154  {
2155  sweptVolCorr *= mesh().time().deltaT().value();
2156  }
2157  else
2158  {
2159  sweptVolCorr *= (2.0/3.0)*mesh().time().deltaT().value();
2160  }
2161  }
2162  else
2163  {
2165  << "Unsupported temporal differencing scheme : "
2166  << ddtScheme << nl
2167  << abort(FatalError);
2168  }
2169 
2170  const scalarField& Sf = aMesh().S();
2171  const vectorField& Nf = aMesh().faceAreaNormals().internalField();
2172 
2173  scalarField deltaHf
2174  (
2175  sweptVolCorr/(Sf*(Nf & facesDisplacementDir()))
2176  );
2177 
2178  for (const word& patchName : fixedFreeSurfacePatches_)
2179  {
2180  label fixedPatchID =
2181  aMesh().boundary().findPatchID(patchName);
2182 
2183  if (fixedPatchID == -1)
2184  {
2186  << "Wrong faPatch name '" << patchName
2187  << "'in the fixedFreeSurfacePatches list"
2188  << " defined in dynamicMeshDict dictionary"
2189  << abort(FatalError);
2190  }
2191 
2192  const labelList& eFaces =
2193  aMesh().boundary()[fixedPatchID].edgeFaces();
2194 
2195  forAll(eFaces, edgeI)
2196  {
2197  deltaHf[eFaces[edgeI]] *= 2.0;
2198  }
2199  }
2200 
2201  controlPoints() += facesDisplacementDir()*deltaHf;
2202 
2203  pointField displacement(pointDisplacement());
2204  correctPointDisplacement(sweptVolCorr, displacement);
2205 
2206  velocityMotionSolver& vMotion =
2207  refCast<velocityMotionSolver>
2208  (
2209  const_cast<motionSolver&>(motion())
2210  );
2211 
2212  pointVectorField& pointMotionU = vMotion.pointMotionU();
2213  pointMotionU.primitiveFieldRef() = Zero;
2214 
2215  fixedValuePointPatchVectorField& fsPatchPointMeshU =
2216  refCast<fixedValuePointPatchVectorField>
2217  (
2218  const_cast<pointPatchVectorField&>
2219  (
2220  pointMotionU.boundaryField()[fsPatchIndex()]
2221  )
2222  );
2223 
2224  fsPatchPointMeshU ==
2225  displacement/mesh().time().deltaT().value();
2226 
2228 
2229  correctContactLinePointNormals();
2230  }
2231  else
2232  {
2233  vectorField displacement
2234  (
2235  mesh().boundaryMesh()[fsPatchIndex()].nPoints(),
2236  Zero
2237  );
2238 
2239  velocityMotionSolver& vMotion =
2240  refCast<velocityMotionSolver>
2241  (
2242  const_cast<motionSolver&>(motion())
2243  );
2244 
2245  pointVectorField& pointMotionU = vMotion.pointMotionU();
2246  pointMotionU.primitiveFieldRef() = Zero;
2247 
2248  fixedValuePointPatchVectorField& fsPatchPointMeshU =
2249  refCast<fixedValuePointPatchVectorField>
2250  (
2251  const_cast<pointPatchVectorField&>
2252  (
2253  pointMotionU.boundaryField()[fsPatchIndex()]
2254  )
2255  );
2256 
2257  fsPatchPointMeshU ==
2258  displacement/mesh().time().deltaT().value();
2259 
2261  }
2262 
2263  updateUs();
2264 
2265  updateSurfactantConcentration();
2266 
2267  return true;
2268 }
2269 
2270 
2272 {
2274  (
2275  aMesh().patch(),
2277  mesh().time().timePath()/"freeSurface",
2278  false // serial only
2279  );
2280  writer.writeGeometry();
2281 }
2282 
2283 
2285 {
2286  // Write control points into VTK
2287  OFstream os
2288  (
2289  mesh().time().timePath()/"freeSurfaceControlPoints.vtk"
2290  );
2291 
2292  Info<< "Writing free surface control points to " << os.name() << nl;
2293 
2294  os << "# vtk DataFile Version 2.0" << nl
2295  << "freeSurfaceControlPoints" << nl
2296  << "ASCII" << nl
2297  << "DATASET POLYDATA" << nl;
2298 
2299  const label nPoints = controlPoints().size();
2300 
2301  os << "POINTS " << nPoints << " float" << nl;
2302  for (const point& p : controlPoints())
2303  {
2304  os << float(p.x()) << ' '
2305  << float(p.y()) << ' '
2306  << float(p.z()) << nl;
2307  }
2308 
2309  os << "VERTICES " << nPoints << ' ' << 2*nPoints << nl;
2310  for (label id = 0; id < nPoints; ++id)
2311  {
2312  os << 1 << ' ' << id << nl;
2313  }
2314 }
2315 
2316 
2317 // ************************************************************************* //
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
Foam::IOobject::NO_WRITE
Definition: IOobject.H:195
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
volFields.H
Foam::vectorIOField
IOField< vector > vectorIOField
vectorField with IO.
Definition: vectorIOField.H:44
Foam::fvc::snGrad
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > snGrad(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvcSnGrad.C:47
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:52
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
backwardDdtScheme.H
Foam::faMesh::Le
const edgeVectorField & Le() const
Return edge length vectors.
Definition: faMesh.C:587
Foam::interfaceTrackingFvMesh::aMesh
faMesh & aMesh()
Return reference to finite area mesh.
Definition: interfaceTrackingFvMesh.H:288
Foam::PrimitivePatch::pointFaces
const labelListList & pointFaces() const
Return point-face addressing.
Definition: PrimitivePatch.C:301
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::IOobject::AUTO_WRITE
Definition: IOobject.H:194
Foam::interfaceTrackingFvMesh::bulkSurfactantConcentration
volScalarField & bulkSurfactantConcentration()
Return volume surfactant concentration field.
Definition: interfaceTrackingFvMesh.C:1986
Foam::PrimitivePatch::edgeFaces
const labelListList & edgeFaces() const
Return edge-face addressing.
Definition: PrimitivePatch.C:262
wedgeFaPatchFields.H
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::faMesh::faces
const faceList & faces() const
Return local patch faces.
Definition: faMeshI.H:98
Foam::IOField
A primitive field of type <T> with automated input and output.
Definition: foamVtkLagrangianWriter.H:61
turbulence
Info<< "Reading field U\n"<< 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\n"<< endl;autoPtr< compressible::turbulenceModel > turbulence(compressible::turbulenceModel::New(rho, U, phi, thermo))
Definition: createFields.H:94
Foam::TimeState::deltaT
dimensionedScalar deltaT() const
Return time step.
Definition: TimeStateI.H:55
Foam::OFstream::name
virtual const fileName & name() const
Read/write access to the name of the stream.
Definition: OSstream.H:107
Foam::dimLength
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:52
Foam::interfaceTrackingFvMesh::surfactantConcentration
areaScalarField & surfactantConcentration()
Return free-surface surfactant concentration field.
Definition: interfaceTrackingFvMesh.C:1962
motionSolver.H
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
slipFvPatchFields.H
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::dimVelocity
const dimensionSet dimVelocity
Foam::vtk::GenericPatchWriter
Write concrete PrimitivePatch faces/points (optionally with fields) as a vtp file or a legacy vtk fil...
Definition: foamVtkGenericPatchWriter.H:65
Foam::fam::laplacian
tmp< faMatrix< Type > > laplacian(const GeometricField< Type, faPatchField, areaMesh > &vf)
Definition: famLaplacian.C:49
Foam::dimDensity
const dimensionSet dimDensity
Foam::dynamicMotionSolverFvMesh::update
virtual bool update()
Update the mesh for both mesh motion and topology change.
Definition: dynamicMotionSolverFvMesh.C:121
fvcMeshPhi.H
Calculate the mesh motion flux and convert fluxes from absolute to relative and back.
Foam::gAverage
Type gAverage(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:604
demandDrivenData.H
Template functions to aid in the implementation of demand driven data.
Foam::sin
dimensionedScalar sin(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:264
foamVtkUIndPatchWriter.H
Foam::faMesh::correctPatchPointNormals
bool correctPatchPointNormals(const label patchID) const
Whether point normals should be corrected for a patch.
Definition: faMesh.C:836
Foam::dynamicMotionSolverFvMesh::init
virtual bool init(const bool doInit)
Initialise all non-demand-driven data.
Definition: dynamicMotionSolverFvMesh.C:72
turbulentTransportModel.H
Foam::interfaceTrackingFvMesh
The interfaceTrackingFvMesh.
Definition: interfaceTrackingFvMesh.H:58
gravityMeshObject.H
Foam::dynamicFvMesh
Abstract base class for geometry and/or topology changing fvMesh.
Definition: dynamicFvMesh.H:78
wallFvPatch.H
Foam::interfaceTrackingFvMesh::writeVTK
void writeVTK() const
Write VTK freeSurface mesh.
Definition: interfaceTrackingFvMesh.C:2271
Foam::fac::grad
tmp< GeometricField< typename outerProduct< vector, Type >::type, faPatchField, areaMesh >> grad(const GeometricField< Type, faePatchField, edgeMesh > &ssf)
Definition: facGrad.C:56
unitConversion.H
Unit conversion functions.
Foam::faceSet
A list of face labels.
Definition: faceSet.H:51
Foam::dimMoles
const dimensionSet dimMoles(0, 0, 0, 0, 1, 0, 0)
Definition: dimensionSets.H:55
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
Foam::faBoundaryMesh::edgeFaces
UPtrList< const labelUList > edgeFaces() const
Return a list of edgeFaces for each patch.
Definition: faBoundaryMesh.C:153
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::correction
tmp< fvMatrix< Type > > correction(const fvMatrix< Type > &)
Foam::dimensioned::value
const Type & value() const
Return const reference to value.
Definition: dimensionedType.C:434
Foam::faMesh::pointAreaNormals
const vectorField & pointAreaNormals() const
Return point area normals.
Definition: faMesh.C:704
Foam::gSum
Type gSum(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:594
faScalarMatrix
Template specialisation for scalar faMatrix.
Foam::singlePhaseTransportModel
A simple single-phase transport model based on viscosityModel.
Definition: singlePhaseTransportModel.H:57
Foam::GeometricField::internalField
const Internal & internalField() const
Return a const-reference to the dimensioned internal field.
Definition: GeometricFieldI.H:43
Foam::dimForce
const dimensionSet dimForce
Foam::velocityMotionSolver
Virtual base class for velocity motion solver.
Definition: velocityMotionSolver.H:58
Foam::DynamicID< polyBoundaryMesh >
Foam::dynamicMotionSolverFvMesh::motion
const motionSolver & motion() const
Return the motionSolver.
Definition: dynamicMotionSolverFvMesh.C:115
Foam::HashSet< label, Hash< label > >
Foam::fac::div
tmp< GeometricField< Type, faPatchField, areaMesh > > div(const GeometricField< Type, faePatchField, edgeMesh > &ssf)
Definition: facDiv.C:50
Foam::pointPatchField< vector >
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
polyPatchID.H
Foam::vtk::formatType::LEGACY_ASCII
Legacy ASCII, legacyAsciiFormatter.
Foam::fam::ddt
tmp< faMatrix< Type > > ddt(const GeometricField< Type, faPatchField, areaMesh > &vf)
Definition: famDdt.C:48
edgeID
label edgeID
Definition: boundaryProcessorFaPatchPoints.H:6
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::vectorField
Field< vector > vectorField
Specialisation of Field<T> for vector.
Definition: primitiveFieldsFwd.H:54
Foam::interfaceTrackingFvMesh::freeSurfacePressureJump
tmp< scalarField > freeSurfacePressureJump()
Return free surface pressure jump.
Definition: interfaceTrackingFvMesh.C:1875
K
CGAL::Exact_predicates_exact_constructions_kernel K
Definition: CGALTriangulation3DKernel.H:58
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
aMesh
faMesh aMesh(mesh)
nu
volScalarField & nu
Definition: readMechanicalProperties.H:176
Foam::areaVectorField
GeometricField< vector, faPatchField, areaMesh > areaVectorField
Definition: areaFieldsFwd.H:58
Foam::deleteDemandDrivenData
void deleteDemandDrivenData(DataPtr &dataPtr)
Definition: demandDrivenData.H:42
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::flush
Ostream & flush(Ostream &os)
Flush stream.
Definition: Ostream.H:361
Foam::processorFaPatch
Processor patch.
Definition: processorFaPatch.H:56
Foam::fam::Sp
tmp< faMatrix< Type > > Sp(const areaScalarField &sp, const GeometricField< Type, faPatchField, areaMesh > &vf)
Definition: famSup.C:86
slipFaPatchFields.H
Foam::interfaceTrackingFvMesh::updateUs
void updateUs()
Update free-surface velocity field.
Definition: interfaceTrackingFvMesh.C:1779
Foam::TimeState::timeIndex
label timeIndex() const noexcept
Return current time index.
Definition: TimeStateI.H:37
Foam::faMesh::edges
const edgeList & edges() const noexcept
Return local patch edges with reordered boundary.
Definition: faMeshI.H:92
Foam::UniformDimensionedField< vector >
velocityLaplacianFvMotionSolver.H
Foam::interfaceTrackingFvMesh::surfaceTensionGrad
tmp< areaVectorField > surfaceTensionGrad()
Return surface tension gradient.
Definition: interfaceTrackingFvMesh.C:2046
Foam::dimArea
const dimensionSet dimArea(sqr(dimLength))
Definition: dimensionSets.H:59
Foam::face::which
label which(const label pointLabel) const
Find local index on face for the point label, same as find()
Definition: faceI.H:163
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
Foam::Field< vector >
Foam::interfaceTrackingFvMesh::p
const volScalarField & p() const
Return constant reference to pressure field.
Definition: interfaceTrackingFvMesh.C:1801
Foam::faMesh::S
const DimensionedField< scalar, areaMesh > & S() const
Return face areas.
Definition: faMesh.C:632
Foam::fv::CrankNicolsonDdtScheme
Second-oder Crank-Nicolson implicit ddt using the current and previous time-step fields as well as th...
Definition: CrankNicolsonDdtScheme.H:116
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
DebugInFunction
#define DebugInFunction
Report an information message using Foam::Info.
Definition: messageStream.H:388
EulerDdtScheme.H
Foam::faMesh::faceAreaNormals
const areaVectorField & faceAreaNormals() const
Return face area normals.
Definition: faMesh.C:682
Foam::edgeInterpolation::lPN
const edgeScalarField & lPN() const
Return reference to PN geodesic distance.
Definition: edgeInterpolation.C:79
Foam::interfaceTrackingFvMesh::pointsDisplacementDir
vectorField & pointsDisplacementDir()
Return reference to point displacement direction field.
Definition: interfaceTrackingFvMesh.C:1929
fixedValueFaPatchFields.H
Foam::PrimitivePatch::pointEdges
const labelListList & pointEdges() const
Return point-edge addressing.
Definition: PrimitivePatch.C:288
patchID
label patchID
Definition: boundaryProcessorFaPatchPoints.H:5
init
mesh init(true)
Foam::dictionary::subDict
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:460
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:42
field
rDeltaTY field()
phi
surfaceScalarField & phi
Definition: setRegionFluidFields.H:8
Foam::edgeScalarField
GeometricField< scalar, faePatchField, edgeMesh > edgeScalarField
Definition: edgeFieldsFwd.H:52
Foam::volScalarField
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:57
Foam::objectRegistry::lookupObject
const Type & lookupObject(const word &name, const bool recursive=false) const
Definition: objectRegistryTemplates.C:434
Foam::pow
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Definition: dimensionedScalar.C:75
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::polyMesh::oldPoints
virtual const pointField & oldPoints() const
Return old points (mesh motion)
Definition: polyMesh.C:1119
timeName
word timeName
Definition: getTimeIndex.H:3
Foam::fac::edgeIntegrate
tmp< GeometricField< Type, faPatchField, areaMesh > > edgeIntegrate(const GeometricField< Type, faePatchField, edgeMesh > &ssf)
Definition: facEdgeIntegrate.C:47
Foam::turbulenceModel
Abstract base class for turbulence models (RAS, LES and laminar).
Definition: turbulenceModel.H:63
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::faBoundaryMesh::findPatchID
label findPatchID(const word &patchName) const
Find patch index given a name, return -1 if not found.
Definition: faBoundaryMesh.C:346
CrankNicolsonDdtScheme.H
interfaceTrackingFvMesh.H
os
OBJstream os(runTime.globalPath()/outputName)
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::interfaceTrackingFvMesh::U
const volVectorField & U() const
Return constant reference to velocity field.
Definition: interfaceTrackingFvMesh.C:1795
Foam::dimensioned< vector >
Foam::writer
Base class for graphics format writing. Entry points are.
Definition: writer.H:81
Foam::PrimitivePatch::localFaces
const List< face_type > & localFaces() const
Return patch faces addressing into local point list.
Definition: PrimitivePatch.C:317
Foam::faMesh::boundary
const faBoundaryMesh & boundary() const noexcept
Return constant reference to boundary mesh.
Definition: faMeshI.H:38
Foam::interfaceTrackingFvMesh::fsNetPhi
const areaScalarField & fsNetPhi() const
Return free-surface net flux.
Definition: interfaceTrackingFvMesh.C:1721
Foam::interfaceTrackingFvMesh::freeSurfaceSnGradU
tmp< vectorField > freeSurfaceSnGradU()
Return free surface normal derivative of velocity.
Definition: interfaceTrackingFvMesh.C:1814
Foam::faMesh::points
const pointField & points() const
Return local patch points.
Definition: faMeshI.H:86
g
const uniformDimensionedVectorField & g
Definition: createFluidFields.H:26
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::surfactantProperties
Definition: surfactantProperties.H:50
Foam::areaScalarField
GeometricField< scalar, faPatchField, areaMesh > areaScalarField
Definition: areaFieldsFwd.H:53
solveBulkSurfactant.H
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::interfaceTrackingFvMesh::freeSurfaceSnGradUn
tmp< scalarField > freeSurfaceSnGradUn()
Return free surface normal derivative of normal velocity comp.
Definition: interfaceTrackingFvMesh.C:1857
Foam::degToRad
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
Definition: unitConversion.H:48
CoNum
scalar CoNum
Definition: compressibleCourantNo.H:31
Foam::interfaceTrackingFvMesh::surfaceTension
areaScalarField & surfaceTension()
Return surface tension field.
Definition: interfaceTrackingFvMesh.C:2010
Foam::PrimitivePatch::localPoints
const Field< point_type > & localPoints() const
Return pointField of points in patch.
Definition: PrimitivePatch.C:359
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:53
Foam::GeometricField::primitiveFieldRef
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field.
Definition: GeometricField.C:766
Foam::GeometricField::correctBoundaryConditions
void correctBoundaryConditions()
Correct boundary field.
Definition: GeometricField.C:940
Foam::faBoundaryMesh::start
label start() const
The start label of the edges in the faMesh edges list.
Definition: faBoundaryMesh.C:267
Foam::normalised
VectorSpace< Form, Cmpt, Ncmpts > normalised(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Definition: VectorSpaceI.H:487
Foam::linearEdgeInterpolate
tmp< GeometricField< Type, faePatchField, edgeMesh > > linearEdgeInterpolate(const GeometricField< Type, faPatchField, areaMesh > &vf)
Definition: linearEdgeInterpolation.H:108
Foam::faPatch::pointLabels
const labelList & pointLabels() const
Return patch point labels.
Definition: faPatch.C:202
Foam::interfaceTrackingFvMesh::motionPointsMask
labelList & motionPointsMask()
Return reference to motion points mask field.
Definition: interfaceTrackingFvMesh.C:1918
U
U
Definition: pEqn.H:72
Foam::face::prevLabel
label prevLabel(const label i) const
Previous vertex on face.
Definition: faceI.H:181
Foam::constant::atomic::a0
const dimensionedScalar a0
Bohr radius: default SI units: [m].
Foam::face::nextLabel
label nextLabel(const label i) const
Next vertex on face.
Definition: faceI.H:175
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::motionSolver
Virtual base class for mesh motion solver.
Definition: motionSolver.H:58
CGAL::indexedCell
An indexed form of CGAL::Triangulation_cell_base_3<K> used to keep track of the Delaunay cells (tets)...
Definition: indexedCell.H:58
Foam::faMesh::faceCurvatures
const areaScalarField & faceCurvatures() const
Return face curvatures.
Definition: faMesh.C:729
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::pointSet
A set of point labels.
Definition: pointSet.H:51
Foam::fv::backwardDdtScheme
Second-order backward-differencing ddt using the current and two previous time-step values.
Definition: backwardDdtScheme.H:61
Foam::foamVersion::patch
const std::string patch
OpenFOAM patch number as a std::string.
Foam::Vector< scalar >
Foam::UPstream::parRun
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
Foam::List< bool >
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:144
Foam::interfaceTrackingFvMesh::writeVTKControlPoints
void writeVTKControlPoints()
Write VTK freeSurface control points.
Definition: interfaceTrackingFvMesh.C:2284
Us
Us
Definition: createFaFields.H:51
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::type
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:590
symmetryFvPatchFields.H
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::interfaceTrackingFvMesh::facesDisplacementDir
vectorField & facesDisplacementDir()
Return reference to control points displacement direction field.
Definition: interfaceTrackingFvMesh.C:1940
Foam::tmp::New
static tmp< T > New(Args &&... args)
Construct tmp of T with forwarding arguments.
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:191
Foam::interfaceTrackingFvMesh::correctUsBoundaryConditions
void correctUsBoundaryConditions()
Correct surface velocity boundary conditions.
Definition: interfaceTrackingFvMesh.C:1732
Foam::velocityMotionSolver::pointMotionU
pointVectorField & pointMotionU()
Return reference to the point motion velocity field.
Definition: velocityMotionSolver.H:102
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::interfaceTrackingFvMesh::phi
const surfaceScalarField & phi() const
Return constant reference to velocity field.
Definition: interfaceTrackingFvMesh.C:1807
Foam::faMesh
Finite area mesh. Used for 2-D non-Euclidian finite area method.
Definition: faMesh.H:82
Foam::fvMesh::time
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:280
Foam::boundaryMesh
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
Definition: boundaryMesh.H:62
twoDPointCorrector.H
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
Cb
CGAL::indexedCell< K > Cb
Definition: CGALTriangulation3Ddefs.H:49
startTime
Foam::label startTime
Definition: checkTimeOptions.H:1
Foam::interfaceTrackingFvMesh::controlPoints
vectorField & controlPoints()
Return control points.
Definition: interfaceTrackingFvMesh.C:1907
timeIndex
label timeIndex
Definition: getTimeIndex.H:30
Foam::interfaceTrackingFvMesh::update
virtual bool update()
Update the mesh for both mesh motion and topology change.
Definition: interfaceTrackingFvMesh.C:2075
sigma
dimensionedScalar sigma("sigma", dimMass/sqr(dimTime), transportProperties)
N
const Vector< label > N(dict.get< Vector< label >>("N"))
p0
const volScalarField & p0
Definition: EEqn.H:36
Foam::gMin
Type gMin(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:593
Foam::interfaceTrackingFvMesh::surfactant
const surfactantProperties & surfactant() const
Return surfactant properties.
Definition: interfaceTrackingFvMesh.C:2034
Foam::dimVolume
const dimensionSet dimVolume(pow3(dimLength))
Definition: dimensionSets.H:60
Foam::PrimitivePatch::meshPoints
const labelList & meshPoints() const
Return labelList of mesh points in patch.
Definition: PrimitivePatch.C:330
Foam::GeometricField< scalar, fvPatchField, volMesh >
Foam::IOobject::NO_READ
Definition: IOobject.H:188
writer
vtk::internalMeshWriter writer(topoMesh, topoCells, vtk::formatType::INLINE_ASCII, runTime.path()/"blockTopology")
Foam::fvMesh::Cf
const surfaceVectorField & Cf() const
Return face centres as surfaceVectorField.
Definition: fvMeshGeometry.C:352
wedgeFaPatch.H
Foam::faMesh::patch
const uindirectPrimitivePatch & patch() const
Return constant reference to primitive patch.
Definition: faMeshI.H:122
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::fv::EulerDdtScheme
Basic first-order Euler implicit/explicit ddt using only the current and previous time-step values.
Definition: EulerDdtScheme.H:60
Foam::neg
dimensionedScalar neg(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:199
Foam::fac::interpolate
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.
boundary
faceListList boundary
Definition: createBlockMesh.H:4
pFaces
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];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } 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};const 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< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
Foam::gMax
Type gMax(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:592
Foam::interfaceTrackingFvMesh::Us
areaVectorField & Us()
Return free-surface velocity field.
Definition: interfaceTrackingFvMesh.C:1688
Foam::interfaceTrackingFvMesh::init
virtual bool init(const bool doInit)
Initialise all non-demand-driven data.
Definition: interfaceTrackingFvMesh.C:1662
Foam::meshObjects::gravity::New
static const gravity & New(const Time &runTime)
Construct on Time.
Definition: gravityMeshObject.H:93
Foam::interfaceTrackingFvMesh::Phis
edgeScalarField & Phis()
Return free-surface fluid flux field.
Definition: interfaceTrackingFvMesh.C:1951
Foam::dictionary::readIfPresent
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:405
Foam::GeometricField::boundaryField
const Boundary & boundaryField() const
Return const-reference to the boundary field.
Definition: GeometricFieldI.H:62
Foam::dimless
const dimensionSet dimless
Dimensionless.
Definition: dimensionSets.C:189
Foam::interfaceTrackingFvMesh::~interfaceTrackingFvMesh
* ~interfaceTrackingFvMesh()
Destructor.
Definition: interfaceTrackingFvMesh.C:1643
Foam::dynamicMotionSolverFvMesh
The dynamicMotionSolverFvMesh.
Definition: dynamicMotionSolverFvMesh.H:53
Foam::fam::div
tmp< faMatrix< Type > > div(const edgeScalarField &flux, const GeometricField< Type, faPatchField, areaMesh > &vf, const word &name)
Definition: famDiv.C:48
Foam::faMesh::areaCentres
const areaVectorField & areaCentres() const
Return face centres as areaVectorField.
Definition: faMesh.C:609
Foam::IOobject::MUST_READ
Definition: IOobject.H:185
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:265