surfaceAlignedSBRStressFvMotionSolver.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) 2015 OpenFOAM Foundation
9  Copyright (C) 2015-2022 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 "pointIndexHit.H"
32 #include "processorPolyPatch.H"
33 #include "fvmLaplacian.H"
34 #include "fvcDiv.H"
35 #include "surfaceInterpolate.H"
36 #include "unitConversion.H"
37 #include "motionDiffusivity.H"
38 #include "fvcSmooth.H"
39 #include "pointMVCWeight.H"
40 #include "dimensionedSymmTensor.H"
41 #include "quaternion.H"
42 #include "fvOptions.H"
43 
44 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 
46 namespace Foam
47 {
48  defineTypeNameAndDebug(surfaceAlignedSBRStressFvMotionSolver, 0);
49 
51  (
52  motionSolver,
53  surfaceAlignedSBRStressFvMotionSolver,
54  dictionary
55  );
56 }
57 
58 
59 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
60 
61 Foam::surfaceAlignedSBRStressFvMotionSolver::
62 surfaceAlignedSBRStressFvMotionSolver
63 (
64  const polyMesh& mesh,
65  const IOdictionary& dict
66 )
67 :
69  surfaceNames_(coeffDict().lookup("surfaces")),
70  surfaceMesh_(surfaceNames_.size()),
71  cellRot_
72  (
73  IOobject
74  (
75  "cellRot",
76  fvMesh_.time().timeName(),
77  fvMesh_,
78  IOobject::NO_READ,
79  IOobject::NO_WRITE
80  ),
81  fvMesh_,
83  ),
84  maxAng_(coeffDict().getOrDefault<scalar>("maxAng", 80)),
85  minAng_(coeffDict().getOrDefault<scalar>("minAng", 20)),
86  accFactor_(coeffDict().getOrDefault<scalar>("accFactor", 1)),
87  smoothFactor_(coeffDict().getOrDefault<scalar>("smoothFactor", 0.9)),
88  nNonOrthogonalCorr_(coeffDict().get<label>("nNonOrthogonalCorr")),
89  pointDisplacement_(pointDisplacement()),
90  sigmaD_
91  (
92  IOobject
93  (
94  "sigmaD",
95  fvMesh_.time().timeName(),
96  fvMesh_,
97  IOobject::READ_IF_PRESENT,
98  IOobject::NO_WRITE
99  ),
100  fvMesh_,
102  ),
103  minSigmaDiff_(coeffDict().getOrDefault<scalar>("minSigmaDiff", 1e-4))
104 {
105  forAll(surfaceNames_, i)
106  {
107  surfaceMesh_.set
108  (
109  i,
110  new triSurfaceMesh
111  (
112  IOobject
113  (
114  surfaceNames_[i],
115  mesh.time().constant(),
116  "triSurface",
117  mesh.time(),
120  )
121  )
122  );
123  }
124 }
125 
126 
127 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
128 
131 {}
132 
133 
134 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
135 
136 
137 void Foam::surfaceAlignedSBRStressFvMotionSolver::calculateCellRot()
138 {
139  cellRot_.primitiveFieldRef() = Zero;
140  pointDisplacement_.primitiveFieldRef() = Zero;
141 
142  // Find intersections
143  pointField start(fvMesh_.nInternalFaces());
144  pointField end(start.size());
145 
146  const vectorField& Cc = fvMesh_.cellCentres();
147  const polyBoundaryMesh& pbm = fvMesh_.boundaryMesh();
148 
149  for (label faceI = 0; faceI < fvMesh_.nInternalFaces(); faceI++)
150  {
151  start[faceI] = Cc[fvMesh_.faceOwner()[faceI]];
152  end[faceI] = Cc[fvMesh_.faceNeighbour()[faceI]];
153  }
154 
155  DynamicList<label> hitCells;
156 
157  forAll(surfaceMesh_, surfi)
158  {
159  List<pointIndexHit> hit(start.size());
160  surfaceMesh_[surfi].findLineAny(start, end, hit);
161 
162  labelField pointsCount(fvMesh_.nPoints(), 1);
163 
164  const vectorField& nf = surfaceMesh_[surfi].faceNormals();
165 
166  const vectorField& SfMesh = fvMesh_.faceAreas();
167 
168  const vectorField nSfMesh(SfMesh/mag(SfMesh));
169 
170  DynamicList<label> cellsHit;
171 
172  forAll(hit, facei)
173  {
174  if (hit[facei].hit())
175  {
176  label rotCellId(-1);
177  const vector& hitPoint = hit[facei].point();
178 
179  if (fvMesh_.isInternalFace(facei))
180  {
181  const point& ownCc = Cc[fvMesh_.faceOwner()[facei]];
182  const point& nbrCc = Cc[fvMesh_.faceNeighbour()[facei]];
183 
184  if (hitPoint.distSqr(ownCc) < hitPoint.distSqr(nbrCc))
185  {
186  rotCellId = fvMesh_.faceOwner()[facei];
187  }
188  else
189  {
190  rotCellId = fvMesh_.faceNeighbour()[facei];
191  }
192  }
193  else
194  {
195  label patchi = pbm.whichPatch(facei);
196  if (isA<processorPolyPatch>(pbm[patchi]))
197  {
198  const point& ownCc = Cc[fvMesh_.faceOwner()[facei]];
199 
200  const vector cCentreOne = ownCc - hitPoint;
201 
202  const vector nbrCc =
203  refCast<const processorPolyPatch>(pbm[patchi])
204  .neighbFaceCellCentres()[facei];
205 
206  const vector cCentreTwo = nbrCc - hitPoint;
207 
208  if (cCentreOne < cCentreTwo)
209  {
210  rotCellId = fvMesh_.faceOwner()[facei];
211  }
212  }
213  }
214 
215  // Note: faces on boundaries that get hit are not included as
216  // the pointDisplacement on boundaries is usually zero for
217  // this solver.
218 
219  // Search for closest direction on faces on mesh
220  // and surface normal.
221  if (rotCellId != -1)
222  {
223  const labelList& cFaces = fvMesh_.cells()[rotCellId];
224 
225  scalar cosMax(-GREAT);
226  label faceId(-1);
227  forAll(cFaces, k)
228  {
229  scalar tmp =
230  mag(nf[hit[facei].index()] & nSfMesh[cFaces[k]]);
231 
232  if (tmp > cosMax)
233  {
234  cosMax = tmp;
235  faceId = cFaces[k];
236  }
237  }
238  if
239  (
240  faceId != -1
241  &&
242  (
243  ::cos(degToRad(minAng_)) > cosMax
244  || cosMax > ::cos(degToRad(maxAng_))
245 
246  )
247  )
248  {
249  cellRot_[rotCellId] =
250  nSfMesh[faceId]^nf[hit[facei].index()];
251 
252  const scalar magRot = mag(cellRot_[rotCellId]);
253 
254  if (magRot > 0)
255  {
256  const scalar theta = ::asin(magRot);
257  quaternion q(cellRot_[rotCellId]/magRot, theta);
258  const tensor R = q.R();
259  const labelList& cPoints =
260  fvMesh_.cellPoints(rotCellId);
261 
262  forAll(cPoints, j)
263  {
264  const label pointId = cPoints[j];
265 
266  pointsCount[pointId]++;
267 
268  const vector pointPos =
269  fvMesh_.points()[pointId];
270 
271  pointDisplacement_[pointId] +=
272  (R & (pointPos - hitPoint))
273  - (pointPos - hitPoint);
274  }
275  }
276  }
277  }
278  }
279  }
280 
281  vectorField& pd = pointDisplacement_.primitiveFieldRef();
282  forAll(pd, pointi)
283  {
284  vector& point = pd[pointi];
285  point /= pointsCount[pointi];
286  }
287  }
288 }
289 
290 
292 {
293  // The points have moved so before interpolation update
294  // the motionSolver accordingly
295  this->movePoints(fvMesh_.points());
296 
297  volVectorField& cellDisp = cellDisplacement();
298 
299  diffusivity().correct();
300 
301  // Calculate rotations on surface intersection
302  calculateCellRot();
303 
304  tmp<volVectorField> tUd
305  (
306  new volVectorField
307  (
308  IOobject
309  (
310  "Ud",
311  fvMesh_.time().timeName(),
312  fvMesh_,
315  ),
316  fvMesh_,
318  cellMotionBoundaryTypes<vector>
319  (
320  pointDisplacement().boundaryField()
321  )
322  )
323  );
324 
325  volVectorField& Ud = tUd.ref();
326 
327  const vectorList& C = fvMesh_.C();
328  forAll(Ud, i)
329  {
330  pointMVCWeight pointInter(fvMesh_, C[i], i);
331  Ud[i] = pointInter.interpolate(pointDisplacement_);
332  }
333 
334  volScalarField Udx(Ud.component(vector::X));
335  fvc::smooth(Udx, smoothFactor_);
336 
337  volScalarField Udy(Ud.component(vector::Y));
338  fvc::smooth(Udy, smoothFactor_);
339 
340  volScalarField Udz(Ud.component(vector::Z));
341  fvc::smooth(Udz, smoothFactor_);
342 
343  Ud.replace(vector::X, Udx);
344  Ud.replace(vector::Y, Udy);
345  Ud.replace(vector::Z, Udz);
346 
347  const volTensorField gradD("gradD", fvc::grad(Ud));
348 
349  tmp<volScalarField> tmu
350  (
351  new volScalarField
352  (
353  IOobject
354  (
355  "mu",
356  fvMesh_.time().timeName(),
357  fvMesh_,
360  ),
361  fvMesh_,
363  )
364  );
365  volScalarField& mu = tmu.ref();
366 
367  const scalarList& V = fvMesh_.V();
368  mu.primitiveFieldRef() = (1.0/V);
369 
370  const volScalarField lambda(-mu);
371 
372  const volSymmTensorField newSigmaD
373  (
374  mu*twoSymm(gradD) + (lambda*I)*tr(gradD)
375  );
376 
377  const volSymmTensorField magNewSigmaD(sigmaD_ + accFactor_*newSigmaD);
378 
379  const scalar diffSigmaD =
380  gSum(mag(sigmaD_.oldTime().primitiveField()))
381  - gSum(mag(magNewSigmaD.primitiveField()));
382 
383  if (mag(diffSigmaD) > minSigmaDiff_)
384  {
385  sigmaD_ = magNewSigmaD;
386  }
387 
388  const dimensionedScalar oneViscosity("viscosity", dimViscosity, 1.0);
389 
390  const surfaceScalarField Df(oneViscosity*diffusivity().operator()());
391 
392  pointDisplacement_.boundaryFieldRef().updateCoeffs();
393 
394  fv::options& fvOptions(fv::options::New(fvMesh_));
395 
396  const volTensorField gradCd(fvc::grad(cellDisp));
397 
398  for (int nonOrth=0; nonOrth<=nNonOrthogonalCorr_; nonOrth++)
399  {
400  fvVectorMatrix DEqn
401  (
403  (
404  2*Df*fvc::interpolate(mu),
405  cellDisp,
406  "laplacian(diffusivity,cellDisplacement)"
407  )
408  + fvc::div
409  (
410  Df*
411  (
413  * (fvMesh_.Sf() & fvc::interpolate(gradCd.T() - gradCd))
414  - fvc::interpolate(lambda)*fvMesh_.Sf()
415  * fvc::interpolate(tr(gradCd))
416  )
417  )
418  ==
419  oneViscosity*fvc::div(sigmaD_)
420  + fvOptions(cellDisp)
421  );
422 
423  fvOptions.constrain(DEqn);
424 
425  // Note: solve uncoupled
426  DEqn.solveSegregatedOrCoupled();
427 
428  fvOptions.correct(cellDisp);
429  }
430 }
431 
432 
433 // ************************************************************************* //
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
List< scalar > scalarList
List of scalar.
Definition: scalarList.H:32
void correct(GeometricField< Type, PatchField, GeoMesh > &field)
Apply correction to field.
GeometricField< symmTensor, fvPatchField, volMesh > volSymmTensorField
Definition: volFieldsFwd.H:85
const polyBoundaryMesh & pbm
dictionary dict
Field< label > labelField
Specialisation of Field<T> for label.
Definition: labelField.H:48
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcGrad.C:47
label faceId(-1)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
GeometricField< tensor, fvPatchField, volMesh > volTensorField
Definition: volFieldsFwd.H:86
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcDiv.C:42
Unit conversion functions.
const dimensionSet dimViscosity
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
Tensor< scalar > tensor
Definition: symmTensor.H:57
Calculate the matrix for the laplacian of the field.
label k
Boltzmann constant.
Ignore writing from objectRegistry::writeObject()
const dimensionSet dimless
Dimensionless.
List< vector > vectorList
List of vector.
Definition: vectorList.H:32
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:360
Lookup type of boundary radiation properties.
Definition: lookup.H:57
GeometricField< vector, fvPatchField, volMesh > volVectorField
Definition: volFieldsFwd.H:82
dimensionedScalar asin(const dimensionedScalar &ds)
Macros for easy insertion into run-time selection tables.
dimensionedSymmTensor twoSymm(const dimensionedSymmTensor &dt)
void smooth(volScalarField &field, const scalar coeff)
Definition: fvcSmooth.C:37
fv::options & fvOptions
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
IOoject and searching on triSurface.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:81
word timeName
Definition: getTimeIndex.H:3
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
Type gSum(const FieldField< Field, Type > &f)
dimensionedScalar cos(const dimensionedScalar &ds)
static const Identity< scalar > I
Definition: Identity.H:100
dimensionedScalar lambda("lambda", dimTime/sqr(dimLength), laminarTransport)
dimensionedScalar tr(const dimensionedSphericalTensor &dt)
const fvMesh & mesh() const
Return reference to the fvMesh to be moved.
Vector< scalar > vector
Definition: vector.H:57
label whichPatch(const label meshFacei) const
Return patch index for a given mesh face index. Uses binary search.
Calculate the divergence of the given field.
void constrain(fvMatrix< Type > &eqn)
Apply constraints to equation.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
const word & constant() const noexcept
Return constant name.
Definition: TimePathsI.H:112
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
defineTypeNameAndDebug(combustionModel, 0)
volScalarField & C
static tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > interpolate(const GeometricField< Type, fvPatchField, volMesh > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
const dimensionedScalar mu
Atomic mass unit.
vector point
Point is a vector.
Definition: point.H:37
#define R(A, B, C, D, E, F, K, M)
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
tmp< fvMatrix< Type > > laplacian(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvmLaplacian.C:41
PtrList< volScalarField > & Y
fvMatrix< vector > fvVectorMatrix
Definition: fvMatricesFwd.H:40
Nothing to be read.
Internal & ref(const bool updateAccessTime=true)
Same as internalFieldRef()
Mesh motion solver for an fvMesh. Based on solving the cell-centre solid-body rotation stress equatio...
Field< vector > vectorField
Specialisation of Field<T> for vector.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
List< label > labelList
A List of labels.
Definition: List.H:62
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
static options & New(const fvMesh &mesh)
Construct fvOptions and register to database if not present.
Definition: fvOptions.C:96
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
Provides functions smooth spread and sweep which use the FaceCellWave algorithm to smooth and redistr...
Namespace for OpenFOAM.
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127