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-2020 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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"
41#include "quaternion.H"
42#include "fvOptions.H"
43
44// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45
46namespace Foam
47{
49
51 (
55 );
56}
57
58
59// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
60
61Foam::surfaceAlignedSBRStressFvMotionSolver::
62surfaceAlignedSBRStressFvMotionSolver
63(
64 const polyMesh& mesh,
65 const IOdictionary& dict
66)
67:
69 surfaceNames_(coeffDict().lookup("surfaces")),
70 surfaceMesh_(surfaceNames_.size()),
71 cellRot_
72 (
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 (
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,
111 (
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
137void 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].hitPoint();
178
179 if (fvMesh_.isInternalFace(facei))
180 {
181 const vector cCOne = Cc[fvMesh_.faceOwner()[facei]];
182 const vector cCTwo = Cc[fvMesh_.faceNeighbour()[facei]];
183
184 if (mag(cCOne - hitPoint) < mag(cCTwo - hitPoint))
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
305 (
307 (
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
335 fvc::smooth(Udx, smoothFactor_);
336
338 fvc::smooth(Udy, smoothFactor_);
339
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
350 (
352 (
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
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
427
428 fvOptions.correct(cellDisp);
429 }
430}
431
432
433// ************************************************************************* //
label k
#define R(A, B, C, D, E, F, K, M)
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
fv::options & fvOptions
Graphite solid properties.
Definition: C.H:53
C()
Construct null.
Definition: C.C:43
const Internal::FieldType & primitiveField() const
Return a const-reference to the internal field.
tmp< GeometricField< Type, PatchField, GeoMesh > > T() const
Return transpose (only if it is a tensor field)
void replace(const direction d, const GeometricField< cmptType, PatchField, GeoMesh > &gcf)
Replace specified field component with content from another field.
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field.
tmp< GeometricField< cmptType, PatchField, GeoMesh > > component(const direction) const
Return a component of the field.
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:57
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
const word & constant() const
Return constant name.
Definition: TimePathsI.H:96
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
Mesh motion solver for an fvMesh. Based on solving the cell-centre solid-body rotation stress equatio...
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition: fvMatrix.H:121
SolverPerformance< Type > solveSegregatedOrCoupled(const dictionary &)
Solve segregated or coupled returning the solution statistics.
Definition: fvMatrixSolve.C:62
const dictionary & solverDict() const
Return the solver dictionary taking into account finalIteration.
Definition: fvMatrix.C:1558
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:290
const fvMesh & mesh() const
Return reference to the fvMesh to be moved.
void constrain(fvMatrix< Type > &eqn)
Apply constraints to equation.
void correct(GeometricField< Type, fvPatchField, volMesh > &field)
Apply correction to field.
Finite-volume options.
Definition: fvOptions.H:59
Virtual base class for mesh motion solver.
Definition: motionSolver.H:61
Container to calculate weights for interpolating directly from vertices of cell using Mean Value Coor...
Type interpolate(const GeometricField< Type, pointPatchField, pointMesh > &psip) const
Interpolate field.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
Lookup type of boundary radiation properties.
Definition: lookup.H:66
Mesh motion solver for an fvMesh. Based on solving the cell-centre solid-body rotation stress equatio...
Tensor of scalars, i.e. Tensor<scalar>.
A class for managing temporary objects.
Definition: tmp.H:65
T & ref() const
Definition: tmpI.H:227
IOoject and searching on triSurface.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
const volScalarField & mu
dynamicFvMesh & mesh
Calculate the divergence of the given field.
Provides functions smooth spread and sweep which use the FaceCellWave algorithm to smooth and redistr...
Calculate the matrix for the laplacian of the field.
label faceId(-1)
word timeName
Definition: getTimeIndex.H:3
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.
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh > > grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcGrad.C:54
void smooth(volScalarField &field, const scalar coeff)
Definition: fvcSmooth.C:44
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcDiv.C:49
tmp< fvMatrix< Type > > laplacian(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvmLaplacian.C:48
Namespace for OpenFOAM.
const dimensionSet dimViscosity
dimensionedScalar asin(const dimensionedScalar &ds)
Type gSum(const FieldField< Field, Type > &f)
const dimensionSet dimless
Dimensionless.
dimensionedScalar tr(const dimensionedSphericalTensor &dt)
List< label > labelList
A List of labels.
Definition: List.H:66
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:52
dimensionedSymmTensor twoSymm(const dimensionedSymmTensor &dt)
static const Identity< scalar > I
Definition: Identity.H:94
vector point
Point is a vector.
Definition: point.H:43
constexpr scalar degToRad() noexcept
Multiplication factor for degrees to radians conversion.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Field< vector > vectorField
Specialisation of Field<T> for vector.
Field< label > labelField
Specialisation of Field<T> for label.
Definition: labelField.H:52
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
dimensionedScalar cos(const dimensionedScalar &ds)
dictionary dict
volScalarField & e
Definition: createFields.H:11
dimensionedScalar lambda("lambda", dimTime/sqr(dimLength), laminarTransport)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
Unit conversion functions.