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