SLTSDdtScheme.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-2018 OpenFOAM Foundation
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28#include "SLTSDdtScheme.H"
29#include "surfaceInterpolate.H"
30#include "fvMatrices.H"
31
32// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
33
34namespace Foam
35{
36
37// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38
39namespace fv
40{
41
42// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43
44template<class Type>
45void SLTSDdtScheme<Type>::relaxedDiag
46(
47 scalarField& rD,
49) const
50{
51 const labelUList& owner = mesh().owner();
52 const labelUList& neighbour = mesh().neighbour();
53 scalarField diag(rD.size(), Zero);
54
55 forAll(owner, facei)
56 {
57 if (phi[facei] > 0.0)
58 {
59 diag[owner[facei]] += phi[facei];
60 rD[neighbour[facei]] += phi[facei];
61 }
62 else
63 {
64 diag[neighbour[facei]] -= phi[facei];
65 rD[owner[facei]] -= phi[facei];
66 }
67 }
68
69 forAll(phi.boundaryField(), patchi)
70 {
71 const fvsPatchScalarField& pphi = phi.boundaryField()[patchi];
72 const labelUList& faceCells = pphi.patch().patch().faceCells();
73
74 forAll(pphi, patchFacei)
75 {
76 if (pphi[patchFacei] > 0.0)
77 {
78 diag[faceCells[patchFacei]] += pphi[patchFacei];
79 }
80 else
81 {
82 rD[faceCells[patchFacei]] -= pphi[patchFacei];
83 }
84 }
85 }
86
87 rD += (1.0/alpha_ - 2.0)*diag;
88}
89
90
91template<class Type>
92tmp<volScalarField> SLTSDdtScheme<Type>::SLrDeltaT() const
93{
94 const surfaceScalarField& phi =
95 mesh().objectRegistry::template
96 lookupObject<surfaceScalarField>(phiName_);
97
98 const dimensionedScalar& deltaT = mesh().time().deltaT();
99
100 tmp<volScalarField> trDeltaT
101 (
103 (
104 IOobject
105 (
106 "rDeltaT",
107 phi.instance(),
108 mesh()
109 ),
110 mesh(),
112 extrapolatedCalculatedFvPatchScalarField::typeName
113 )
114 );
115
116 volScalarField& rDeltaT = trDeltaT.ref();
117
118 relaxedDiag(rDeltaT, phi);
119
120 if (phi.dimensions() == dimensionSet(0, 3, -1, 0, 0))
121 {
122 rDeltaT.primitiveFieldRef() = max
123 (
124 rDeltaT.primitiveField()/mesh().V(),
125 scalar(1)/deltaT.value()
126 );
127 }
128 else if (phi.dimensions() == dimensionSet(1, 0, -1, 0, 0))
129 {
130 const volScalarField& rho =
131 mesh().objectRegistry::template lookupObject<volScalarField>
132 (
133 rhoName_
134 ).oldTime();
135
136 rDeltaT.primitiveFieldRef() = max
137 (
138 rDeltaT.primitiveField()/(rho.primitiveField()*mesh().V()),
139 scalar(1)/deltaT.value()
140 );
141 }
142 else
143 {
145 << "Incorrect dimensions of phi: " << phi.dimensions()
146 << abort(FatalError);
147 }
148
149 rDeltaT.correctBoundaryConditions();
150
151 return trDeltaT;
152}
153
154
155template<class Type>
156tmp<GeometricField<Type, fvPatchField, volMesh>>
158(
159 const dimensioned<Type>& dt
160)
161{
162 const volScalarField rDeltaT(SLrDeltaT());
163
164 IOobject ddtIOobject
165 (
166 "ddt("+dt.name()+')',
167 mesh().time().timeName(),
168 mesh()
169 );
170
171 if (mesh().moving())
172 {
174 (
176 (
177 ddtIOobject,
178 mesh(),
180 )
181 );
182
183 tdtdt.ref().primitiveFieldRef() =
184 rDeltaT.primitiveField()*dt.value()*(1.0 - mesh().V0()/mesh().V());
185
186 return tdtdt;
187 }
188 else
189 {
191 (
193 (
194 ddtIOobject,
195 mesh(),
198 )
199 );
200 }
201}
202
203
204template<class Type>
207(
209)
210{
211 const volScalarField rDeltaT(SLrDeltaT());
212
213 IOobject ddtIOobject
214 (
215 "ddt("+vf.name()+')',
216 mesh().time().timeName(),
217 mesh()
218 );
219
220 if (mesh().moving())
221 {
223 (
225 (
226 ddtIOobject,
227 mesh(),
228 rDeltaT.dimensions()*vf.dimensions(),
229 rDeltaT.primitiveField()*
230 (
231 vf.primitiveField()
232 - vf.oldTime().primitiveField()*mesh().V0()/mesh().V()
233 ),
234 rDeltaT.boundaryField()*
235 (
236 vf.boundaryField() - vf.oldTime().boundaryField()
237 )
238 )
239 );
240 }
241 else
242 {
244 (
246 (
247 ddtIOobject,
248 rDeltaT*(vf - vf.oldTime())
249 )
250 );
251 }
252}
253
254
255template<class Type>
258(
259 const dimensionedScalar& rho,
261)
262{
263 const volScalarField rDeltaT(SLrDeltaT());
264
265 IOobject ddtIOobject
266 (
267 "ddt("+rho.name()+','+vf.name()+')',
268 mesh().time().timeName(),
269 mesh()
270 );
271
272 if (mesh().moving())
273 {
275 (
277 (
278 ddtIOobject,
279 mesh(),
280 rDeltaT.dimensions()*rho.dimensions()*vf.dimensions(),
281 rDeltaT.primitiveField()*rho.value()*
282 (
283 vf.primitiveField()
284 - vf.oldTime().primitiveField()*mesh().V0()/mesh().V()
285 ),
286 rDeltaT.boundaryField()*rho.value()*
287 (
288 vf.boundaryField() - vf.oldTime().boundaryField()
289 )
290 )
291 );
292 }
293 else
294 {
296 (
298 (
299 ddtIOobject,
300 rDeltaT*rho*(vf - vf.oldTime())
301 )
302 );
303 }
304}
305
306
307template<class Type>
310(
311 const volScalarField& rho,
313)
314{
315 const volScalarField rDeltaT(SLrDeltaT());
316
317 IOobject ddtIOobject
318 (
319 "ddt("+rho.name()+','+vf.name()+')',
320 mesh().time().timeName(),
321 mesh()
322 );
323
324 if (mesh().moving())
325 {
327 (
329 (
330 ddtIOobject,
331 mesh(),
332 rDeltaT.dimensions()*rho.dimensions()*vf.dimensions(),
333 rDeltaT.primitiveField()*
334 (
335 rho.primitiveField()*vf.primitiveField()
336 - rho.oldTime().primitiveField()
337 *vf.oldTime().primitiveField()*mesh().V0()/mesh().V()
338 ),
339 rDeltaT.boundaryField()*
340 (
341 rho.boundaryField()*vf.boundaryField()
342 - rho.oldTime().boundaryField()
343 *vf.oldTime().boundaryField()
344 )
345 )
346 );
347 }
348 else
349 {
351 (
353 (
354 ddtIOobject,
355 rDeltaT*(rho*vf - rho.oldTime()*vf.oldTime())
356 )
357 );
358 }
359}
360
361
362template<class Type>
365(
366 const volScalarField& alpha,
367 const volScalarField& rho,
369)
370{
371 const volScalarField rDeltaT(SLrDeltaT());
372
373 IOobject ddtIOobject
374 (
375 "ddt("+alpha.name()+','+rho.name()+','+vf.name()+')',
376 mesh().time().timeName(),
377 mesh()
378 );
379
380 if (mesh().moving())
381 {
383 (
385 (
386 ddtIOobject,
387 mesh(),
388 rDeltaT.dimensions()
389 *alpha.dimensions()*rho.dimensions()*vf.dimensions(),
390 rDeltaT.primitiveField()*
391 (
392 alpha.primitiveField()
393 *rho.primitiveField()
394 *vf.primitiveField()
395
396 - alpha.oldTime().primitiveField()
397 *rho.oldTime().primitiveField()
398 *vf.oldTime().primitiveField()*mesh().Vsc0()/mesh().Vsc()
399 ),
400 rDeltaT.boundaryField()*
401 (
402 alpha.boundaryField()
403 *rho.boundaryField()
404 *vf.boundaryField()
405
406 - alpha.oldTime().boundaryField()
407 *rho.oldTime().boundaryField()
408 *vf.oldTime().boundaryField()
409 )
410 )
411 );
412 }
413 else
414 {
416 (
418 (
419 ddtIOobject,
420 rDeltaT
421 *(
422 alpha*rho*vf
423 - alpha.oldTime()*rho.oldTime()*vf.oldTime()
424 )
425 )
426 );
427 }
428}
429
430
431template<class Type>
434(
436)
437{
439 (
441 (
442 vf,
444 )
445 );
446
447 fvMatrix<Type>& fvm = tfvm.ref();
448
449 scalarField rDeltaT(SLrDeltaT()().primitiveField());
450
451 fvm.diag() = rDeltaT*mesh().V();
452
453 if (mesh().moving())
454 {
455 fvm.source() = rDeltaT*vf.oldTime().primitiveField()*mesh().V0();
456 }
457 else
458 {
459 fvm.source() = rDeltaT*vf.oldTime().primitiveField()*mesh().V();
460 }
461
462 return tfvm;
463}
464
465
466template<class Type>
469(
470 const dimensionedScalar& rho,
472)
473{
475 (
477 (
478 vf,
479 rho.dimensions()*vf.dimensions()*dimVol/dimTime
480 )
481 );
482 fvMatrix<Type>& fvm = tfvm.ref();
483
484 scalarField rDeltaT(SLrDeltaT()().primitiveField());
485
486 fvm.diag() = rDeltaT*rho.value()*mesh().V();
487
488 if (mesh().moving())
489 {
490 fvm.source() = rDeltaT
491 *rho.value()*vf.oldTime().primitiveField()*mesh().V0();
492 }
493 else
494 {
495 fvm.source() = rDeltaT
496 *rho.value()*vf.oldTime().primitiveField()*mesh().V();
497 }
498
499 return tfvm;
500}
501
502
503template<class Type>
506(
507 const volScalarField& rho,
509)
510{
512 (
514 (
515 vf,
516 rho.dimensions()*vf.dimensions()*dimVol/dimTime
517 )
518 );
519 fvMatrix<Type>& fvm = tfvm.ref();
520
521 scalarField rDeltaT(SLrDeltaT()().primitiveField());
522
523 fvm.diag() = rDeltaT*rho.primitiveField()*mesh().V();
524
525 if (mesh().moving())
526 {
527 fvm.source() = rDeltaT
528 *rho.oldTime().primitiveField()
529 *vf.oldTime().primitiveField()*mesh().V0();
530 }
531 else
532 {
533 fvm.source() = rDeltaT
534 *rho.oldTime().primitiveField()
535 *vf.oldTime().primitiveField()*mesh().V();
536 }
537
538 return tfvm;
539}
540
541
542template<class Type>
545(
546 const volScalarField& alpha,
547 const volScalarField& rho,
549)
550{
552 (
554 (
555 vf,
556 alpha.dimensions()*rho.dimensions()*vf.dimensions()*dimVol/dimTime
557 )
558 );
559 fvMatrix<Type>& fvm = tfvm.ref();
560
561 scalarField rDeltaT(SLrDeltaT()().primitiveField());
562
563 fvm.diag() =
564 rDeltaT*alpha.primitiveField()*rho.primitiveField()*mesh().Vsc();
565
566 if (mesh().moving())
567 {
568 fvm.source() = rDeltaT
569 *alpha.oldTime().primitiveField()
570 *rho.oldTime().primitiveField()
571 *vf.oldTime().primitiveField()*mesh().Vsc0();
572 }
573 else
574 {
575 fvm.source() = rDeltaT
576 *alpha.oldTime().primitiveField()
577 *rho.oldTime().primitiveField()
578 *vf.oldTime().primitiveField()*mesh().Vsc();
579 }
580
581 return tfvm;
582}
583
584
585template<class Type>
588(
591)
592{
593 const surfaceScalarField rDeltaT(fvc::interpolate(SLrDeltaT()));
594
595 fluxFieldType phiUf0(mesh().Sf() & Uf.oldTime());
596 fluxFieldType phiCorr
597 (
598 phiUf0 - fvc::dotInterpolate(mesh().Sf(), U.oldTime())
599 );
600
601 return tmp<fluxFieldType>
602 (
603 new fluxFieldType
604 (
606 (
607 "ddtCorr(" + U.name() + ',' + Uf.name() + ')',
608 mesh().time().timeName(),
609 mesh()
610 ),
611 this->fvcDdtPhiCoeff(U.oldTime(), phiUf0, phiCorr)
612 *rDeltaT*phiCorr
613 )
614 );
615}
616
617
618template<class Type>
621(
623 const fluxFieldType& phi
624)
625{
626 const surfaceScalarField rDeltaT(fvc::interpolate(SLrDeltaT()));
627
628 fluxFieldType phiCorr
629 (
630 phi.oldTime() - fvc::dotInterpolate(mesh().Sf(), U.oldTime())
631 );
632
633 return tmp<fluxFieldType>
634 (
635 new fluxFieldType
636 (
638 (
639 "ddtCorr(" + U.name() + ',' + phi.name() + ')',
640 mesh().time().timeName(),
641 mesh()
642 ),
643 this->fvcDdtPhiCoeff(U.oldTime(), phi.oldTime(), phiCorr)
644 *rDeltaT*phiCorr
645 )
646 );
647}
648
649
650template<class Type>
653(
654 const volScalarField& rho,
657)
658{
659 const surfaceScalarField rDeltaT(fvc::interpolate(SLrDeltaT()));
660
661 if
662 (
663 U.dimensions() == dimVelocity
664 && Uf.dimensions() == dimDensity*dimVelocity
665 )
666 {
668 (
669 rho.oldTime()*U.oldTime()
670 );
671
672 fluxFieldType phiUf0(mesh().Sf() & Uf.oldTime());
673 fluxFieldType phiCorr(phiUf0 - fvc::dotInterpolate(mesh().Sf(), rhoU0));
674
675 return tmp<fluxFieldType>
676 (
677 new fluxFieldType
678 (
680 (
681 "ddtCorr("
682 + rho.name() + ',' + U.name() + ',' + Uf.name() + ')',
683 mesh().time().timeName(),
684 mesh()
685 ),
686 this->fvcDdtPhiCoeff(rhoU0, phiUf0, phiCorr, rho.oldTime())
687 *rDeltaT*phiCorr
688 )
689 );
690 }
691 else if
692 (
693 U.dimensions() == dimDensity*dimVelocity
694 && Uf.dimensions() == dimDensity*dimVelocity
695 )
696 {
697 fluxFieldType phiUf0(mesh().Sf() & Uf.oldTime());
698 fluxFieldType phiCorr
699 (
700 phiUf0 - fvc::dotInterpolate(mesh().Sf(), U.oldTime())
701 );
702
703 return tmp<fluxFieldType>
704 (
705 new fluxFieldType
706 (
708 (
709 "ddtCorr("
710 + rho.name() + ',' + U.name() + ',' + Uf.name() + ')',
711 mesh().time().timeName(),
712 mesh()
713 ),
714 this->fvcDdtPhiCoeff
715 (
716 U.oldTime(),
717 phiUf0,
718 phiCorr,
719 rho.oldTime()
720 )*rDeltaT*phiCorr
721 )
722 );
723 }
724 else
725 {
727 << "dimensions of Uf are not correct"
728 << abort(FatalError);
729
730 return fluxFieldType::null();
731 }
732}
733
734
735template<class Type>
738(
739 const volScalarField& rho,
741 const fluxFieldType& phi
742)
743{
744 dimensionedScalar rDeltaT = 1.0/mesh().time().deltaT();
745
746 if
747 (
748 U.dimensions() == dimVelocity
749 && phi.dimensions() == rho.dimensions()*dimVelocity*dimArea
750 )
751 {
753 (
754 rho.oldTime()*U.oldTime()
755 );
756
757 fluxFieldType phiCorr
758 (
759 phi.oldTime() - fvc::dotInterpolate(mesh().Sf(), rhoU0)
760 );
761
762 return tmp<fluxFieldType>
763 (
764 new fluxFieldType
765 (
767 (
768 "ddtCorr("
769 + rho.name() + ',' + U.name() + ',' + phi.name() + ')',
770 mesh().time().timeName(),
771 mesh()
772 ),
773 this->fvcDdtPhiCoeff
774 (
775 rhoU0,
776 phi.oldTime(),
777 phiCorr,
778 rho.oldTime()
779 )*rDeltaT*phiCorr
780 )
781 );
782 }
783 else if
784 (
785 U.dimensions() == rho.dimensions()*dimVelocity
786 && phi.dimensions() == rho.dimensions()*dimVelocity*dimArea
787 )
788 {
789 fluxFieldType phiCorr
790 (
791 phi.oldTime() - fvc::dotInterpolate(mesh().Sf(), U.oldTime())
792 );
793
794 return tmp<fluxFieldType>
795 (
796 new fluxFieldType
797 (
799 (
800 "ddtCorr("
801 + rho.name() + ',' + U.name() + ',' + phi.name() + ')',
802 mesh().time().timeName(),
803 mesh()
804 ),
805 this->fvcDdtPhiCoeff
806 (
807 U.oldTime(),
808 phi.oldTime(),
809 phiCorr,
810 rho.oldTime()
811 )*rDeltaT*phiCorr
812 )
813 );
814 }
815 else
816 {
818 << "dimensions of phi are not correct"
819 << abort(FatalError);
820
821 return fluxFieldType::null();
822 }
823}
824
825
826template<class Type>
828(
830)
831{
833 (
835 (
837 (
838 "meshPhi",
839 mesh().time().timeName(),
840 mesh(),
843 false
844 ),
845 mesh(),
847 )
848 );
849
850 tmeshPhi.ref().setOriented();
851
852 return tmeshPhi;
853}
854
855
856// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
857
858} // End namespace fv
859
860// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
861
862} // End namespace Foam
863
864// ************************************************************************* //
surfaceScalarField & phi
const dimensionSet & dimensions() const
Return dimensions.
const GeometricField< Type, PatchField, GeoMesh > & oldTime() const
Return old time field.
const Internal::FieldType & primitiveField() const
Return a const-reference to the internal field.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:65
This boundary condition is not designed to be evaluated; it is assmued that the value is assigned via...
Generic dimensioned Type class.
const dimensionSet & dimensions() const
Return const reference to dimensions.
const Type & value() const
Return const reference to value.
const word & name() const
Return const reference to name.
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Definition: fvMatrix.H:121
Field< Type > & source() noexcept
Definition: fvMatrix.H:458
tmp< GeometricField< Type, fvPatchField, volMesh > > fvcDdt(const dimensioned< Type > &)
tmp< fluxFieldType > fvcDdtPhiCorr(const GeometricField< Type, fvPatchField, volMesh > &U, const fluxFieldType &phi)
tmp< fvMatrix< Type > > fvmDdt(const GeometricField< Type, fvPatchField, volMesh > &)
tmp< surfaceScalarField > meshPhi(const GeometricField< Type, fvPatchField, volMesh > &)
tmp< fluxFieldType > fvcDdtUfCorr(const GeometricField< Type, fvPatchField, volMesh > &U, const GeometricField< Type, fvsPatchField, surfaceMesh > &Uf)
scalarField & diag()
Definition: lduMatrix.C:192
A class for managing temporary objects.
Definition: tmp.H:65
T & ref() const
Definition: tmpI.H:227
U
Definition: pEqn.H:72
dynamicFvMesh & mesh
tmp< volScalarField > trDeltaT
Definition: createRDeltaT.H:3
autoPtr< surfaceVectorField > Uf
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
A special matrix type and solver, designed for finite volume solutions of scalar equations.
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.
static tmp< GeometricField< typename innerProduct< vector, Type >::type, fvsPatchField, surfaceMesh > > dotInterpolate(const surfaceVectorField &Sf, const GeometricField< Type, fvPatchField, volMesh > &tvf)
Interpolate field onto faces.
Namespace for OpenFOAM.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
const dimensionSet dimless
Dimensionless.
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:53
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:82
const dimensionSet dimArea(sqr(dimLength))
Definition: dimensionSets.H:59
const dimensionSet dimVelocity
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
errorManip< error > abort(error &err)
Definition: errorManip.H:144
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
error FatalError
const dimensionSet dimVolume(pow3(dimLength))
Definition: dimensionSets.H:60
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
const dimensionSet dimDensity
UList< label > labelUList
A UList of labels.
Definition: UList.H:85
fvsPatchField< scalar > fvsPatchScalarField
const dimensionSet dimVol(dimVolume)
Older spelling for dimVolume.
Definition: dimensionSets.H:64
labelList fv(nPoints)
volScalarField & alpha
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333