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