Loading...
Searching...
No Matches
fusedGaussLaplacianScheme.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) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2024 M. Janssens
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
30#include "fvcSurfaceOps.H"
31#include "surfaceInterpolate.H"
32#include "fvcDiv.H"
33#include "fvcGrad.H"
34#include "fvMatrices.H"
35
36// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
37
38namespace Foam
39{
40
41// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
42
43namespace fv
44{
45
46// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
47
48template<class Type, class GType>
49template<class E1, class E2>
50void fusedGaussLaplacianScheme<Type, GType>::fvmCorrection
51(
52 fvMatrix<Type>& fvm,
53 const dimensionSet& gammaDim,
54 const E1& gammaMagSf,
55 const E2& corr
56)
57{
58 typedef GeometricField<Type, fvsPatchField, surfaceMesh> surfaceType;
59
60 const auto& vf = fvm.psi();
61 const fvMesh& mesh = vf.mesh();
62 const auto V = mesh.V().expr();
63
64 if (mesh.fluxRequired(vf.name()))
65 {
66 fvm.faceFluxCorrectionPtr() = std::make_unique<surfaceType>
67 (
68 IOobject
69 (
70 "faceFluxCorr",
71 mesh.time().timeName(),
72 mesh,
76 ),
77 mesh,
78 gammaDim
79 *mesh.magSf().dimensions()
80 *corr.data().dimensions()
81 );
82 auto& faceFluxCorr = *fvm.faceFluxCorrectionPtr();
83
84 faceFluxCorr = corr*gammaMagSf;
85
86 fvm.source() =
87 fvm.source().expr()
88 - (
90 (
91 faceFluxCorr
92 )().primitiveField().expr()
93 *V
94 );
95 }
96 else
97 {
98 surfaceType faceFluxCorr
99 (
100 IOobject
101 (
102 "faceFluxCorr",
103 mesh.time().timeName(),
104 mesh,
108 ),
109 mesh,
110 gammaDim
111 *mesh.magSf().dimensions()
112 *corr.data().dimensions()
113 );
114 faceFluxCorr = corr*gammaMagSf;
115
116 fvm.source() =
117 fvm.source().expr()
118 - (
120 (
121 faceFluxCorr
122 )().primitiveField().expr()
123 *V
124 );
125 }
126}
127
128
129template<class Type, class GType>
132(
133 const surfaceScalarField& gammaMagSf,
134 const surfaceScalarField& deltaCoeffs,
136)
137{
139 << "fusedGaussLaplacianScheme<Type, GType>::fvmLaplacianUncorrected on "
140 << vf.name()
141 << " with gammaMagSf " << gammaMagSf.name()
142 << " with deltaCoeffs " << deltaCoeffs.name()
143 << endl;
144
146 (
148 (
149 vf,
150 deltaCoeffs.dimensions()*gammaMagSf.dimensions()*vf.dimensions()
151 )
152 );
153 fvMatrix<Type>& fvm = tfvm.ref();
154
155 //fvm.upper() = deltaCoeffs.primitiveField()*gammaMagSf.primitiveField();
157 (
158 fvm.upper(),
159 deltaCoeffs.primitiveField(),
160 gammaMagSf.primitiveField()
161 );
162 fvm.negSumDiag();
163
164 forAll(vf.boundaryField(), patchi)
165 {
166 const fvPatchField<Type>& pvf = vf.boundaryField()[patchi];
167 const fvsPatchScalarField& pGamma = gammaMagSf.boundaryField()[patchi];
168 const fvsPatchScalarField& pDeltaCoeffs =
169 deltaCoeffs.boundaryField()[patchi];
170
171 auto& intCoeffs = fvm.internalCoeffs()[patchi];
172 auto& bouCoeffs = fvm.boundaryCoeffs()[patchi];
173
174 if (pvf.coupled())
175 {
176 //intCoeffs = pGamma*pvf.gradientInternalCoeffs(pDeltaCoeffs);
178 (
179 intCoeffs,
180 pGamma,
181 pvf.gradientInternalCoeffs(pDeltaCoeffs)()
182 );
183 //bouCoeffs = -pGamma*pvf.gradientBoundaryCoeffs(pDeltaCoeffs);
185 (
186 bouCoeffs,
187 pGamma,
188 pvf.gradientBoundaryCoeffs(pDeltaCoeffs)()
189 );
190 bouCoeffs.negate();
191 }
192 else
193 {
194 //intCoeffs = pGamma*pvf.gradientInternalCoeffs();
196 (
197 intCoeffs,
198 pGamma,
200 );
201 //bouCoeffs = -pGamma*pvf.gradientBoundaryCoeffs();
203 (
204 bouCoeffs,
205 pGamma,
207 );
208 bouCoeffs.negate();
209 }
210 }
211
212 return tfvm;
213}
214
215
216template<class Type, class GType>
217tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
218fusedGaussLaplacianScheme<Type, GType>::gammaSnGradCorr
219(
220 const surfaceVectorField& SfGammaCorr,
221 const GeometricField<Type, fvPatchField, volMesh>& vf
222)
223{
224 const fvMesh& mesh = this->mesh();
225
226 DebugPout<< "fusedGaussLaplacianScheme<Type, GType>::gammaSnGradCorr on "
227 << vf.name() << " with SfGammCorr " << SfGammaCorr.name() << endl;
228
229 tmp<GeometricField<Type, fvsPatchField, surfaceMesh>> tgammaSnGradCorr
230 (
231 new GeometricField<Type, fvsPatchField, surfaceMesh>
232 (
233 IOobject
234 (
235 "gammaSnGradCorr("+vf.name()+')',
236 vf.instance(),
237 mesh,
240 ),
241 mesh,
242 SfGammaCorr.dimensions()
243 *vf.dimensions()*mesh.deltaCoeffs().dimensions()
244 )
245 );
246 auto& gammaSnGradCorr = tgammaSnGradCorr.ref();
247 gammaSnGradCorr.oriented() = SfGammaCorr.oriented();
248
249 for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; cmpt++)
250 {
251 gammaSnGradCorr.replace
252 (
253 cmpt,
254 fvc::dotInterpolate(SfGammaCorr, fvc::grad(vf.component(cmpt)))
255 );
256 }
257
258 return tgammaSnGradCorr;
259}
260
261
262/*
263template<class Type, class GType>
264void fusedGaussLaplacianScheme<Type, GType>::gradComponent
265(
266 const surfaceScalarField& weights,
267 const GeometricField<Type, fvPatchField, volMesh>& vf,
268 const direction cmpt,
269 GeometricField<Type, fvPatchField, volMesh>& gGrad
270)
271{
272 gGrad = Zero;
273
274 // Calculate grad of vf.component(cmpt)
275 fvc::GaussOp
276 (
277 vf,
278 weights,
279 componentInterpolate<Type>(cmpt),
280 gGrad
281 );
282}
283template<class Type, class GType>
284tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
285fusedGaussLaplacianScheme<Type, GType>::gammaSnGradCorr
286(
287 const surfaceScalarField& weights,
288 const GeometricField<GType, fvPatchField, volMesh>& gamma,
289 const GeometricField<Type, fvPatchField, volMesh>& vf
290)
291{
292 const fvMesh& mesh = this->mesh();
293
294 tmp<GeometricField<Type, fvsPatchField, surfaceMesh>> tgammaSnGradCorr
295 (
296 new GeometricField<Type, fvsPatchField, surfaceMesh>
297 (
298 IOobject
299 (
300 "gammaSnGradCorr("+vf.name()+')',
301 vf.instance(),
302 mesh,
303 IOobject::NO_READ,
304 IOobject::NO_WRITE
305 ),
306 mesh,
307 gamma.dimensions()
308 *vf.dimensions()*mesh.deltaCoeffs().dimensions()
309 )
310 );
311 auto& gammaSnGradCorr = tgammaSnGradCorr.ref();
312
313 gammaSnGradCorr.oriented() = gamma.oriented();
314
315
316 GeometricField<Type, fvPatchField, volMesh> gradCmptFld
317 (
318 IOobject
319 (
320 vf.name() + ".component()",
321 vf.instance(),
322 mesh,
323 IOobject::NO_READ,
324 IOobject::NO_WRITE,
325 false
326 ),
327 mesh,
328 vf.dimensions()
329 );
330
331 for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; cmpt++)
332 {
333 // Calculate fvc::grad(vf.component(cmpt)) into gradCmptFld
334 gradComponent
335 (
336 weights,
337 vf,
338 cmpt,
339
340 gradCmptFld
341 );
342
343 //gammaSnGradCorr.replace
344 //(
345 // cmpt,
346 // fvc::dotInterpolate(SfGammaCorr, gradCmptFld)
347 //);
348
349
350 fvc::interpolate
351 (
352 weights,
353
354 gradCmptFld, // fvc::grad(vf.component(cmpt))
355
356 gamma, // weight field
357
358 tanInterpolate<Type, GType>(cmpt),
359
360 gammaSnGradCorr
361 );
362 }
363
364 return tgammaSnGradCorr;
365}
367
368
369// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
370
371template<class Type, class GType>
374(
376)
377{
379 //typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
380
381 tmp<FieldType> tresult
382 (
383 new FieldType
384 (
386 (
387 "laplacian(" + vf.name() + ')',
388 vf.instance(),
389 vf.mesh(),
392 ),
393 vf.mesh(),
396 )
397 );
398 FieldType& result = tresult.ref();
399
401 << "fusedGaussLaplacianScheme<Type, GType>::fvcLaplacian on "
402 << vf.name()
403 << " to generate " << result.name() << endl;
404
405 // Note: cannot use fvc::GaussOp since specialised handling on boundary.
406 // Maybe bypass for processor boundaries?
407
408 const auto tdeltaCoeffs(this->tsnGradScheme_().deltaCoeffs(vf));
409 const auto& deltaCoeffs = tdeltaCoeffs();
410
411
412 const fvMesh& mesh = vf.mesh();
413
414 if (this->tsnGradScheme_().corrected())
415 {
416 // Problem when instantiating for tensors - outerProduct not defined.
417 // scalar/vector specialisations in *Schemes.C file.
418
419 FatalErrorInFunction<< "Corrected snGrad not supported for field "
420 << vf.name() << exit(FatalError);
421
422 //typedef typename outerProduct<vector, Type>::type GradType;
423 //typedef GeometricField<GradType, fvPatchField, volMesh> GradFieldType;
425 //tmp<SurfaceFieldType> tfaceGrad
426 //(
427 // new SurfaceFieldType
428 // (
429 // IOobject
430 // (
431 // "snGradCorr("+vf.name()+')',
432 // vf.instance(),
433 // mesh,
434 // IOobject::NO_READ,
435 // IOobject::NO_WRITE
436 // ),
437 // mesh,
438 // vf.dimensions()
439 // )
440 //);
441 //
442 //{
443 // // Calculate gradient
444 // tmp<GradFieldType> tgGrad
445 // (
446 // gradScheme<Type>::New
447 // (
448 // mesh,
449 // mesh.gradScheme("grad(" + vf.name() + ')')
450 // )().grad(vf, "grad(" + vf.name() + ')')
451 // );
452 // const auto& gGrad = tgGrad();
453 //
454 // // Doing a dotinterpolate with nonOrthCorrectionVectors
455 // const auto dotInterpolate = [&]
456 // (
457 // const vector& area,
458 // const scalar lambda,
459 //
460 // const GradType& ownVal,
461 // const GradType& neiVal,
462 //
463 // const vector& dotVector,
464 //
465 // Type& result
466 // )
467 // {
468 // result = dotVector&(lambda*(ownVal - neiVal) + neiVal);
469 // };
470 //
471 // fvc::interpolate
472 // (
473 // mesh.surfaceInterpolation::weights(), // linear interp
474 // gGrad, // volume field
475 // mesh.nonOrthCorrectionVectors(),// surface multiplier
476 // dotInterpolate,
477 // tfaceGrad.ref()
478 // );
479 //}
480 //const auto& faceGrad = tfaceGrad();
481 //
482 //const auto snGrad = [&]
483 //(
484 // const vector& Sf,
485 // const scalar dc,
486 // const Type& ownVal,
487 // const Type& neiVal,
488 // const Type& correction
489 //) -> Type
490 //{
491 // const auto snGrad(dc*(neiVal-ownVal) + correction);
492 // return mag(Sf)*snGrad;
493 //};
494 //
495 //fvc::surfaceSnSum
496 //(
497 // deltaCoeffs,
498 // vf,
499 // faceGrad, // face-based addition
500 // snGrad,
501 // result,
502 // false // avoid boundary evaluation until volume division
503 //);
504 }
505 else
506 {
507 const auto snGrad = [&]
508 (
509 const vector& Sf,
510 const scalar dc,
511 const Type& ownVal,
512 const Type& neiVal
513 ) -> Type
514 {
515 const auto snGrad(dc*(neiVal-ownVal));
516 return mag(Sf)*snGrad;
517 };
518
520 (
521 deltaCoeffs,
522 vf,
523 snGrad,
524 result,
525 false // avoid boundary evaluation until volume division
526 );
527 }
528
529 result.primitiveFieldRef() /= mesh.V();
530 result.correctBoundaryConditions();
543{
545 << "fusedGaussLaplacianScheme<Type, GType>::fvcLaplacian on "
546 << vf.name() << " with gamma " << gamma.name() << endl;
548 return fvcLaplacian(this->tinterpGammaScheme_().interpolate(gamma)(), vf);
549}
550
551
552template<class Type, class GType>
555(
558)
559{
560 DebugPout<< "fusedGaussLaplacianScheme<Type, GType>::fvmLaplacian on "
561 << vf.name() << " with gamma " << gamma.name() << endl;
562
563 const fvMesh& mesh = this->mesh();
564
565 const surfaceVectorField Sn(mesh.Sf()/mesh.magSf());
566 const surfaceVectorField SfGamma(mesh.Sf() & gamma);
568 (
569 SfGamma & Sn
570 );
571 const surfaceVectorField SfGammaCorr(SfGamma - SfGammaSn*Sn);
572
573 tmp<fvMatrix<Type>> tfvm = fvmLaplacianUncorrected
574 (
575 SfGammaSn,
576 this->tsnGradScheme_().deltaCoeffs(vf),
577 vf
578 );
579 fvMatrix<Type>& fvm = tfvm.ref();
580
582 = gammaSnGradCorr(SfGammaCorr, vf);
583
584 if (this->tsnGradScheme_().corrected())
585 {
586 tfaceFluxCorrection.ref() +=
587 SfGammaSn*this->tsnGradScheme_().correction(vf);
588 }
589
590 fvm.source() -= mesh.V()*fvc::div(tfaceFluxCorrection())().primitiveField();
591
592 if (mesh.fluxRequired(vf.name()))
593 {
594 fvm.faceFluxCorrectionPtr(tfaceFluxCorrection.ptr());
595 }
597 return tfvm;
598}
599
600
601template<class Type, class GType>
604(
607)
608{
609 DebugPout<< "fusedGaussLaplacianScheme<Type, GType>::fvmLaplacian on "
610 << vf.name() << " with gamma " << gamma.name() << endl;
611 return fvmLaplacian(this->tinterpGammaScheme_().interpolate(gamma)(), vf);
612}
613
614
615template<class Type, class GType>
618(
621)
622{
623 DebugPout<< "fusedGaussLaplacianScheme<Type, GType>::fvcLaplacian on "
624 << vf.name() << " with gamma " << gamma.name() << endl;
625
626 const fvMesh& mesh = this->mesh();
627
628 const surfaceVectorField Sn(mesh.Sf()/mesh.magSf());
629 const surfaceVectorField SfGamma(mesh.Sf() & gamma);
631 (
632 SfGamma & Sn
633 );
634 const surfaceVectorField SfGammaCorr(SfGamma - SfGammaSn*Sn);
635
637 (
639 (
640 SfGammaSn*this->tsnGradScheme_().snGrad(vf)
641 + gammaSnGradCorr(SfGammaCorr, vf)
642 )
643 );
644
645 tLaplacian.ref().rename
646 (
647 "laplacian(" + gamma.name() + ',' + vf.name() + ')'
648 );
649
650 return tLaplacian;
651}
652
653
654// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
655
656} // End namespace fv
657
658// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
659
660} // End namespace Foam
661
662// ************************************************************************* //
const Mesh & mesh() const noexcept
Return const reference to mesh.
const dimensionSet & dimensions() const noexcept
Return dimensions.
orientedType oriented() const noexcept
Return oriented type.
Generic GeometricField class.
const Internal::FieldType & primitiveField() const noexcept
Return a const-reference to the internal field values.
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
tmp< GeometricField< cmptType, PatchField, GeoMesh > > component(const direction) const
Return a component of the field.
@ NO_REGISTER
Do not request registration (bool: false).
@ NO_READ
Nothing to be read.
@ 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 word & name() const noexcept
Return the object name.
Definition IOobjectI.H:205
const fileName & instance() const noexcept
Read access to instance path component.
Definition IOobjectI.H:289
Generic dimensioned Type class.
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition fvMatrix.H:118
Mesh data needed to do the Finite Volume discretisation.
Definition fvMesh.H:85
virtual bool coupled() const
True if the patch field is coupled.
static const word & extrapolatedCalculatedType() noexcept
The type name for extrapolatedCalculated patch fields combines zero-gradient and calculated.
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
virtual tmp< Field< Type > > gradientInternalCoeffs() const
Return the matrix diagonal coefficients corresponding to the evaluation of the gradient of this patch...
virtual tmp< Field< Type > > gradientBoundaryCoeffs() const
Return the matrix source coefficients corresponding to the evaluation of the gradient of this patchFi...
virtual tmp< GeometricField< Type, fvPatchField, volMesh > > fvcLaplacian(const GeometricField< Type, fvPatchField, volMesh > &)
virtual tmp< fvMatrix< Type > > fvmLaplacian(const GeometricField< GType, fvsPatchField, surfaceMesh > &, const GeometricField< Type, fvPatchField, volMesh > &)
static tmp< fvMatrix< Type > > fvmLaplacianUncorrected(const surfaceScalarField &gammaMagSf, const surfaceScalarField &deltaCoeffs, const GeometricField< Type, fvPatchField, volMesh > &)
tmp< snGradScheme< Type > > tsnGradScheme_
tmp< surfaceInterpolationScheme< GType > > tinterpGammaScheme_
const fvMesh & mesh() const
Return mesh reference.
A class for managing temporary objects.
Definition tmp.H:75
T * ptr() const
Return managed pointer for reuse, or clone() the object reference.
Definition tmpI.H:256
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition tmpI.H:235
const scalar gamma
Definition EEqn.H:9
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
A special matrix type and solver, designed for finite volume solutions of scalar equations.
Calculate the divergence of the given field.
Calculate the gradient of the given field.
Surface integrate surfaceField creating a volField. Surface sum a surfaceField creating a volField.
#define DebugPout
Report an information message using Foam::Pout.
const expr V(m.psi().mesh().V())
Namespace for finite-volume.
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh > > grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition fvcGrad.C:47
static tmp< GeometricField< typename innerProduct< vector, Type >::type, fvsPatchField, surfaceMesh > > dotInterpolate(const surfaceVectorField &Sf, const GeometricField< Type, fvPatchField, volMesh > &tvf)
Interpolate field onto faces.
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition fvcDiv.C:42
void surfaceSnSum(const surfaceScalarField &deltaCoeffs, const GeometricField< Type, fvPatchField, volMesh > &vf, const CellToFaceOp &cop, GeometricField< ResultType, fvPatchField, volMesh > &result, const bool doCorrectBoundaryConditions)
sum of snGrad
Namespace of functions to calculate implicit derivatives returning a matrix.
Namespace for OpenFOAM.
GeometricField< vector, fvsPatchField, surfaceMesh > surfaceVectorField
const dimensionSet dimArea(sqr(dimLength))
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
uint8_t direction
Definition direction.H:49
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
static scalar Sn(const scalar a, const scalar x)
Definition invIncGamma.C:64
bool interpolate(const vector &p1, const vector &p2, const vector &o, vector &n, scalar l)
Definition curveTools.C:75
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
Vector< scalar > vector
Definition vector.H:57
void multiply(DimensionedField< Type, GeoMesh > &result, const DimensionedField< Type, GeoMesh > &f1, const DimensionedField< scalar, GeoMesh > &f2)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
fvsPatchField< scalar > fvsPatchScalarField
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299