Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
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"
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].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 =
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 auto tUd = volVectorField::New
305 (
306 "Ud",
308 fvMesh_,
310 cellMotionBoundaryTypes<vector>
311 (
312 pointDisplacement().boundaryField()
313 )
314 );
315 auto& Ud = tUd.ref();
316
317 const vectorList& C = fvMesh_.C();
318 forAll(Ud, i)
319 {
320 pointMVCWeight pointInter(fvMesh_, C[i], i);
321 Ud[i] = pointInter.interpolate(pointDisplacement_);
322 }
323
324 volScalarField Udx(Ud.component(vector::X));
325 fvc::smooth(Udx, smoothFactor_);
326
327 volScalarField Udy(Ud.component(vector::Y));
328 fvc::smooth(Udy, smoothFactor_);
329
330 volScalarField Udz(Ud.component(vector::Z));
331 fvc::smooth(Udz, smoothFactor_);
332
333 Ud.replace(vector::X, Udx);
334 Ud.replace(vector::Y, Udy);
335 Ud.replace(vector::Z, Udz);
336
337 const volTensorField gradD("gradD", fvc::grad(Ud));
338
339 auto tmu = volScalarField::New
340 (
341 "mu",
343 fvMesh_,
345 );
346 auto& mu = tmu.ref();
347
348 const scalarList& V = fvMesh_.V();
349 mu.primitiveFieldRef() = (1.0/V);
350
351 const volScalarField lambda(-mu);
352
353 const volSymmTensorField newSigmaD
354 (
355 mu*twoSymm(gradD) + (lambda*I)*tr(gradD)
356 );
357
358 const volSymmTensorField magNewSigmaD(sigmaD_ + accFactor_*newSigmaD);
359
360 const scalar diffSigmaD =
361 gSum(mag(sigmaD_.oldTime().primitiveField()))
362 - gSum(mag(magNewSigmaD.primitiveField()));
363
364 if (mag(diffSigmaD) > minSigmaDiff_)
365 {
366 sigmaD_ = magNewSigmaD;
367 }
368
369 const dimensionedScalar oneViscosity("viscosity", dimViscosity, 1.0);
370
371 const surfaceScalarField Df(oneViscosity*diffusivity().operator()());
372
373 pointDisplacement_.boundaryFieldRef().updateCoeffs();
374
376
377 const volTensorField gradCd(fvc::grad(cellDisp));
378
379 for (int nonOrth=0; nonOrth<=nNonOrthogonalCorr_; nonOrth++)
380 {
381 fvVectorMatrix DEqn
382 (
384 (
385 2*Df*fvc::interpolate(mu),
386 cellDisp,
387 "laplacian(diffusivity,cellDisplacement)"
388 )
389 + fvc::div
390 (
391 Df*
392 (
394 * (fvMesh_.Sf() & fvc::interpolate(gradCd.T() - gradCd))
395 - fvc::interpolate(lambda)*fvMesh_.Sf()
396 * fvc::interpolate(tr(gradCd))
397 )
398 )
399 ==
400 oneViscosity*fvc::div(sigmaD_)
401 + fvOptions(cellDisp)
402 );
403
404 fvOptions.constrain(DEqn);
405
406 // Note: solve uncoupled
407 DEqn.solveSegregatedOrCoupled();
408
409 fvOptions.correct(cellDisp);
410 }
411}
412
413
414// ************************************************************************* //
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.
const polyBoundaryMesh & pbm
fv::options & fvOptions
Graphite solid properties.
Definition C.H:49
C() noexcept
Default construct.
Definition C.C:36
label size() const noexcept
The number of elements in list.
Definition DLListBase.H:194
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
static tmp< GeometricField< vector, fvPatchField, volMesh > > New(const word &name, IOobjectOption::registerOption regOpt, const Mesh &mesh, const dimensionSet &dims, const word &patchFieldType=fvPatchField< vector >::calculatedType())
tmp< GeometricField< Type, PatchField, GeoMesh > > T() const
Return transpose (only if it is a tensor field).
const Internal::FieldType & primitiveField() const noexcept
Return a const-reference to the internal field values.
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
@ NO_REGISTER
Do not request registration (bool: false).
@ NO_READ
Nothing to be read.
@ READ_IF_PRESENT
Reading is optional [identical to LAZY_READ].
@ MUST_READ
Reading required.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
const Time & time() const noexcept
Return Time associated with the objectRegistry.
Definition IOobject.C:456
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
pointVectorField & pointDisplacement() noexcept
Return reference to the point motion displacement field.
Mesh motion solver for an fvMesh. Based on solving the cell-centre solid-body rotation stress equatio...
volVectorField & cellDisplacement()
Return reference to the cell motion displacement field.
SolverPerformance< Type > solveSegregatedOrCoupled(const dictionary &)
Solve segregated or coupled returning the solution statistics.
const fvMesh & fvMesh_
The fvMesh to be moved.
wordList cellMotionBoundaryTypes(const typename GeometricField< Type, pointPatchField, pointMesh >::Boundary &pmUbf) const
Create the corresponding patch types for cellMotion from those.
const fvMesh & mesh() const
Return reference to the fvMesh to be moved.
void correct(GeometricField< Type, PatchField, GeoMesh > &field)
Apply correction to field.
void constrain(fvMatrix< Type > &eqn)
Apply constraints to equation.
Finite-volume options, which is an IOdictionary of values and a fv::optionList.
Definition fvOptions.H:69
static options & New(const fvMesh &mesh)
Construct fvOptions and register to database if not present otherwise lookup and return.
Definition fvOptions.C:116
Virtual base class for mesh motion solver.
const dictionary & coeffDict() const
Const access to the coefficients dictionary.
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.
virtual void movePoints(const pointField &)
Update local data for geometry changes.
A polyBoundaryMesh is a polyPatch list with registered IO, a reference to the associated polyMesh,...
label whichPatch(const label meshFacei) const
Return patch index for a given mesh face index. Uses binary search.
Mesh consisting of general polyhedral cells.
Definition polyMesh.H:79
Quaternion class used to perform rotations in 3D space.
Definition quaternion.H:54
Lookup type of boundary radiation properties.
Definition lookup.H:60
Mesh motion solver for an fvMesh. Based on solving the cell-centre solid-body rotation stress equatio...
A class for managing temporary objects.
Definition tmp.H:75
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:142
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
const expr V(m.psi().mesh().V())
const char * end
Definition SVGTools.H:223
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:47
void smooth(volScalarField &field, const scalar coeff)
Definition fvcSmooth.C:37
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition fvcDiv.C:42
tmp< fvMatrix< Type > > laplacian(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Namespace for OpenFOAM.
const dimensionSet dimViscosity
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
Definition typeInfo.H:172
dimensionedScalar asin(const dimensionedScalar &ds)
Type gSum(const FieldField< Field, Type > &f)
GeometricField< vector, fvPatchField, volMesh > volVectorField
const dimensionSet dimless
Dimensionless.
dimensionedScalar tr(const dimensionedSphericalTensor &dt)
List< label > labelList
A List of labels.
Definition List.H:62
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
GeometricField< scalar, fvPatchField, volMesh > volScalarField
dimensionedSymmTensor twoSymm(const dimensionedSymmTensor &dt)
static const Identity< scalar > I
Definition Identity.H:100
List< vector > vectorList
List of vector.
Definition vectorList.H:32
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
Tensor< scalar > tensor
Definition symmTensor.H:57
dimensioned< symmTensor > dimensionedSymmTensor
Dimensioned tensor obtained from generic dimensioned type.
constexpr scalar degToRad() noexcept
Multiplication factor for degrees to radians conversion.
GeometricField< tensor, fvPatchField, volMesh > volTensorField
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
Definition typeInfo.H:87
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
fvMatrix< vector > fvVectorMatrix
Field< vector > vectorField
Specialisation of Field<T> for vector.
Field< label > labelField
Specialisation of Field<T> for label.
Definition labelField.H:48
GeometricField< symmTensor, fvPatchField, volMesh > volSymmTensorField
vector point
Point is a vector.
Definition point.H:37
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
vectorField pointField
pointField is a vectorField.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Vector< scalar > vector
Definition vector.H:57
List< scalar > scalarList
List of scalar.
Definition scalarList.H:32
dimensionedScalar cos(const dimensionedScalar &ds)
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
dictionary dict
volScalarField & e
dimensionedScalar lambda("lambda", dimTime/sqr(dimLength), laminarTransport)
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
Unit conversion functions.