Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/fem/src/MaterialModels.F90
3203 views
1
!/*****************************************************************************/
2
! *
3
! * Elmer, A Finite Element Software for Multiphysical Problems
4
! *
5
! * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
6
! *
7
! * This library is free software; you can redistribute it and/or
8
! * modify it under the terms of the GNU Lesser General Public
9
! * License as published by the Free Software Foundation; either
10
! * version 2.1 of the License, or (at your option) any later version.
11
! *
12
! * This library is distributed in the hope that it will be useful,
13
! * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
! * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
! * Lesser General Public License for more details.
16
! *
17
! * You should have received a copy of the GNU Lesser General Public
18
! * License along with this library (in file ../LGPL-2.1); if not, write
19
! * to the Free Software Foundation, Inc., 51 Franklin Street,
20
! * Fifth Floor, Boston, MA 02110-1301 USA
21
! *
22
! *****************************************************************************/
23
!
24
!/******************************************************************************
25
! *
26
! * Authors: Juha Ruokolainen, Thomas Zwinger
27
! * Email: [email protected]
28
! * Web: http://www.csc.fi/elmer
29
! * Address: CSC - IT Center for Science Ltd.
30
! * Keilaranta 14
31
! * 02101 Espoo, Finland
32
! *
33
! * Original Date: 24 Apr 1997
34
! *
35
! *****************************************************************************/
36
37
!> \ingroup ElmerLib
38
!> \}
39
40
!---------------------------------------------------------------------
41
!> Module for material models of fluids mainly.
42
!---------------------------------------------------------------------
43
44
45
MODULE MaterialModels
46
47
USE DefUtils
48
49
IMPLICIT NONE
50
INTEGER, PARAMETER :: Incompressible = 0, UserDefined1 = 1,UserDefined2 = 2
51
INTEGER, PARAMETER :: PerfectGas1 = 3, PerfectGas2 = 4, PerfectGas3 = 5, Thermal = 6
52
53
54
CONTAINS
55
56
57
58
!------------------------------------------------------------------------------
59
!> Return second invariant.
60
!> Note: Actually SQUARE of the second invariant of velocity is returned
61
!------------------------------------------------------------------------------
62
FUNCTION SecondInvariant( Velo,dVelodx,CtrMetric,Symb ) RESULT(SecInv)
63
!------------------------------------------------------------------------------
64
65
REAL(KIND=dp), OPTIONAL :: CtrMetric(3,3),Symb(3,3,3)
66
REAL(KIND=dp) :: Velo(3),dVelodx(3,3),SecInv
67
68
!------------------------------------------------------------------------------
69
70
INTEGER :: i,j,k,l
71
REAL(KIND=dp) :: CovMetric(3,3),s,t
72
73
SecInv = 0.0D0
74
75
IF ( CurrentCoordinateSystem() == Cartesian ) THEN
76
!------------------------------------------------------------------------------
77
78
DO i=1,3
79
DO j=1,3
80
s = dVelodx(i,j) + dVelodx(j,i)
81
SecInv = SecInv + s * s
82
END DO
83
END DO
84
!------------------------------------------------------------------------------
85
ELSE IF ( CurrentCoordinateSystem() == AxisSymmetric ) THEN
86
87
SecInv = (2*dVelodx(1,1))**2 + (2*dVelodx(2,2))**2 + &
88
2*(dVelodx(1,2) + dVelodx(2,1))**2 + (2*Velo(1)*symb(1,3,3))**2
89
90
ELSE
91
92
!------------------------------------------------------------------------------
93
CovMetric = CtrMetric
94
CALL InvertMatrix( CovMetric,3 )
95
96
DO i=1,3
97
DO j=1,3
98
s = 0.0d0
99
t = 0.0d0
100
101
DO k=1,3
102
s = s + CovMetric(i,k) * dVelodx(k,j) + &
103
CovMetric(j,k) * dVelodx(k,i)
104
105
t = t + CtrMetric(j,k) * dVelodx(i,k) + &
106
CtrMetric(i,k) * dVelodx(j,k)
107
108
DO l=1,3
109
s = s - CovMetric(i,k) * Symb(l,j,k) * Velo(l)
110
s = s - CovMetric(j,k) * Symb(l,i,k) * Velo(l)
111
112
t = t - CtrMetric(j,k) * Symb(l,k,i) * Velo(l)
113
t = t - CtrMetric(i,k) * Symb(l,k,j) * Velo(l)
114
END DO
115
END DO
116
SecInv = SecInv + s * t
117
END DO
118
END DO
119
!------------------------------------------------------------------------------
120
121
END IF
122
!------------------------------------------------------------------------------
123
END FUNCTION SecondInvariant
124
!------------------------------------------------------------------------------
125
126
127
128
#if 0
129
this ise not in USE
130
!------------------------------------------------------------------------------
131
SUBROUTINE FrictionHeat( Heat,Viscosity,Ux,Uy,Uz,Element,Nodes )
132
!------------------------------------------------------------------------------
133
REAL(KIND=dp) :: Heat(:),Viscosity(:),Ux(:),Uy(:),Uz(:)
134
TYPE(Nodes_t) :: Nodes
135
TYPE(Element_t) :: Element
136
!------------------------------------------------------------------------------
137
REAL(KIND=dp) :: Basis(MAX_ELEMENT_NODES),dBasisdx(MAX_ELEMENT_NODES,3)
138
REAL(KIND=dp) :: s,u,v,w,SqrtMetric,SqrtElementMetric,Velo(3)
139
REAL(KIND=dp) :: Metric(3,3),dVelodx(3,3), &
140
CtrMetric(3,3),Symb(3,3,3),dSymb(3,3,3,3)
141
142
LOGICAL :: stat
143
INTEGER :: i,j,n
144
!------------------------------------------------------------------------------
145
146
n = Element % TYPE % NumberOfNodes
147
DO i=1,n
148
u = Element % TYPE % NodeU(i)
149
v = Element % TYPE % NodeV(i)
150
w = Element % TYPE % NodeW(i)
151
!------------------------------------------------------------------------------
152
! Basis function values & derivatives at the calculation point
153
!------------------------------------------------------------------------------
154
stat = ElementInfo( Element,Nodes, u, v, w, &
155
SqrtElementMetric, Basis,dBasisdx )
156
!------------------------------------------------------------------------------
157
! Coordinate system dependent information
158
!------------------------------------------------------------------------------
159
CALL CoordinateSystemInfo( Metric,SqrtMetric,Symb,dSymb, &
160
Nodes % x(i),Nodes % y(i),Nodes % z(i) )
161
!------------------------------------------------------------------------------
162
163
DO j=1,3
164
dVelodx(1,j) = SUM( Ux(1:n) * dBasisdx(1:n,j) )
165
dVelodx(2,j) = SUM( Uy(1:n) * dBasisdx(1:n,j) )
166
dVelodx(3,j) = SUM( Uz(1:n) * dBasisdx(1:n,j) )
167
END DO
168
169
Velo(1) = Ux(i)
170
Velo(2) = Uy(i)
171
Velo(3) = Uz(i)
172
Heat(i) = 0.5d0*Viscosity(i)*SecondInvariant(Velo,dVelodx,Metric,Symb)
173
END DO
174
175
!------------------------------------------------------------------------------
176
END SUBROUTINE FrictionHeat
177
!------------------------------------------------------------------------------
178
#endif
179
180
181
182
!------------------------------------------------------------------------------
183
!> Returns effective viscosity for Navier-Stokes equation.
184
!> The viscosity model may be either some nonnewtonian material law,
185
!> or from turbulence models, but not from both at the same time.
186
!------------------------------------------------------------------------------
187
FUNCTION EffectiveViscosity( Viscosity,Density,Ux,Uy,Uz,Element, &
188
Nodes,n,nd,u,v,w, muder, LocalIP ) RESULT(mu)
189
!------------------------------------------------------------------------------
190
191
USE ModelDescription
192
193
REAL(KIND=dp) :: Viscosity,Density,u,v,w,mu,Ux(:),Uy(:),Uz(:)
194
REAL(KIND=dp), OPTIONAL :: muder
195
TYPE(Nodes_t) :: Nodes
196
INTEGER :: n,nd
197
INTEGER, OPTIONAL :: LocalIP
198
TYPE(Element_t),POINTER :: Element
199
200
!------------------------------------------------------------------------------
201
REAL(KIND=dp) :: Basis(nd),dBasisdx(nd,3)
202
REAL(KIND=dp) :: ss,s,SqrtMetric,SqrtElementMetric,Velo(3)
203
REAL(KIND=dp) :: Metric(3,3), dVelodx(3,3), CtrMetric(3,3), &
204
Symb(3,3,3), dSymb(3,3,3,3)
205
206
INTEGER :: i,j,k
207
LOGICAL :: stat,GotIt,UseEUsrf=.FALSE.
208
209
CHARACTER(:), ALLOCATABLE :: ViscosityFlag, TemperatureName, EnhcmntFactFlag
210
TYPE(ValueList_t), POINTER :: Material
211
REAL(KIND=dp) :: x, y, z, c1n(n), c2n(n), c3n(n), c4n(n), &
212
c1, c2, c3, c4, c5, c6, c7, Temp, NodalTemperature(n), Tlimit, TempCoeff, &
213
h, A1, A2, Q1, Q2, R, NodalEhF(n), EhF, ArrheniusFactor
214
215
! Temperature is needed for thermal models
216
TYPE(Variable_t), POINTER :: TempSol
217
REAL(KIND=dp), POINTER :: Temperature(:)
218
INTEGER, POINTER :: TempPerm(:)
219
INTEGER(KIND=AddrInt) :: Fnc
220
TYPE(Variable_t), POINTER :: Var
221
REAL(KIND=dp) :: dist,F2,F3
222
REAL(KIND=dp) :: KE_K, KE_E, KE_Z, CT, TimeScale,Clip, Cmu, Vals(n)
223
CHARACTER(:), ALLOCATABLE :: str
224
LOGICAL :: SetArrheniusFactor=.FALSE.
225
226
!------------------------------------------------------------------------------
227
mu = Viscosity
228
IF ( PRESENT(muder) ) muder=0
229
230
k = ListGetInteger( CurrentModel % Bodies(Element % BodyId) % Values, 'Material', &
231
minv=1, maxv=CurrentModel % NumberOFMaterials )
232
233
Material => CurrentModel % Materials(k) % Values
234
235
ViscosityFlag = ListGetString( Material,'Viscosity Model', GotIt)
236
237
IF(.NOT. gotIt) RETURN
238
!------------------------------------------------------------------------------
239
! Basis function values & derivatives at the calculation point
240
!------------------------------------------------------------------------------
241
stat = ElementInfo( Element,Nodes,u,v,w, &
242
SqrtElementMetric, Basis,dBasisdx )
243
!------------------------------------------------------------------------------
244
! Coordinate system dependent information
245
!------------------------------------------------------------------------------
246
x = SUM( Nodes % x(1:n) * Basis(1:n) )
247
y = SUM( Nodes % y(1:n) * Basis(1:n) )
248
z = SUM( Nodes % z(1:n) * Basis(1:n) )
249
CALL CoordinateSystemInfo( Metric,SqrtMetric,Symb,dSymb,x,y,z )
250
!------------------------------------------------------------------------------
251
DO j=1,3
252
dVelodx(1,j) = SUM( Ux(1:nd)*dBasisdx(1:nd,j) )
253
dVelodx(2,j) = SUM( Uy(1:nd)*dBasisdx(1:nd,j) )
254
dVelodx(3,j) = SUM( Uz(1:nd)*dBasisdx(1:nd,j) )
255
END DO
256
257
Velo(1) = SUM( Basis(1:nd) * Ux(1:nd) )
258
Velo(2) = SUM( Basis(1:nd) * Uy(1:nd) )
259
Velo(3) = SUM( Basis(1:nd) * Uz(1:nd) )
260
261
! This is the square of shearrate which results to 1/2 in exponent
262
! Also the derivative is taken with respect to the square
263
!-------------------------------------------------------------------
264
ss = 0.5_dp * SecondInvariant(Velo,dVelodx,Metric,Symb)
265
266
267
SELECT CASE( ViscosityFlag )
268
269
270
CASE('glen')
271
c2n = ListGetReal( Material, 'Glen Exponent', n, Element % NodeIndexes, GotIt ) ! this is the real exponent, n, not 1/n
272
IF (.NOT.GotIt) c2n(1:n) = 3.0_dp
273
c2 = SUM( Basis(1:n) * c2n(1:n) )
274
s = ss/4.0_dp ! the second invariant is not taken from the strain rate tensor, but rather 2*strain rate tensor (that's why we divide by 4 = 2**2)
275
276
SetArrheniusFactor = GetLogical(Material, 'Set Arrhenius Factor', GotIt)
277
IF ( (.NOT.GotIt) .OR. .NOT.(SetArrheniusFactor)) THEN
278
NodalTemperature(1:n) = ListGetReal(Material, 'Constant Temperature', n, Element % NodeIndexes, GotIt) !we are happy as is
279
IF(.NOT.GotIt) THEN !we have to find a temperature field
280
281
TemperatureName = GetString(Material, 'Temperature Field Variable', GotIt)
282
IF (.NOT.GotIt) TemperatureName = 'Temperature'
283
TempSol => VariableGet( CurrentModel % Variables,TRIM(TemperatureName))
284
IF ( ASSOCIATED( TempSol) ) THEN
285
TempPerm => TempSol % Perm
286
Temperature => TempSol % Values
287
Temp = SUM(Basis(1:n) * Temperature(TempPerm(Element % NodeIndexes(1:n))))
288
ELSE
289
WRITE(Message, '(A,A,A)') 'Could not find variable ',&
290
TRIM(TemperatureName),' to inquire temperature field for Glen'
291
CALL FATAL('EffectiveViscosity',Message)
292
END IF
293
294
ELSE
295
Temp = SUM(Basis(1:n) * NodalTemperature(1:n))
296
END IF
297
298
R = GetConstReal( CurrentModel % Constants,'Gas Constant',GotIt)
299
IF (.NOT.GotIt) R = 8.314_dp
300
! lets for the time being have this hardcoded
301
Tlimit = GetConstReal(Material, 'Limit Temperature', GotIt)
302
IF (.NOT.GotIt) THEN
303
Tlimit = -10.0_dp
304
CALL INFO('EffectiveViscosity','Limit Temperature not found. Setting to -10', Level=5)
305
END IF
306
A1 = GetConstReal(Material, 'Rate Factor 1', GotIt)
307
IF (.NOT.GotIt) THEN
308
A1 = 3.985d-13
309
CALL INFO('EffectiveViscosity','Rate Factor 1 not found. Setting to 3.985e-13', Level=5)
310
END IF
311
A2 = GetConstReal(Material, 'Rate Factor 2', GotIt)
312
IF (.NOT.GotIt) THEN
313
A2 = 1.916d03
314
CALL INFO('EffectiveViscosity','Rate Factor 2 not found. Setting to 1.916E03', Level=5)
315
END IF
316
Q1 = GetConstReal(Material, 'Activation Energy 1', GotIt)
317
IF (.NOT.GotIt) THEN
318
Q1 = 60.0d03
319
CALL INFO('EffectiveViscosity','Activation Energy 1 not found. Setting to 60.0E03', Level=5)
320
END IF
321
Q2 = GetConstReal(Material, 'Activation Energy 2', GotIt)
322
IF (.NOT.GotIt) THEN
323
Q2 = 139.0d03
324
CALL INFO('EffectiveViscosity','Activation Energy 2 not found. Setting to 139.0d03', Level=5)
325
END IF
326
327
IF (Temp <= Tlimit) THEN
328
ArrheniusFactor = A1 * EXP( -Q1/(R * (273.15_dp + Temp)))
329
ELSE IF((Tlimit<Temp) .AND. (Temp <= 0.0_dp)) THEN
330
ArrheniusFactor = A2 * EXP( -Q2/(R * (273.15_dp + Temp)))
331
ELSE
332
ArrheniusFactor = A2 * EXP( -Q2/(R * (273.15_dp)))
333
CALL INFO('EffectiveViscosity',&
334
'Positive Temperature detected in Glen - limiting to zero!', Level = 5)
335
END IF
336
ELSE
337
ArrheniusFactor = GetConstReal(Material,'Arrhenius Factor', GotIt)
338
IF (.NOT.(GotIt)) THEN
339
CALL FATAL('EffectiveViscosity',&
340
'<Set Arrhenius Factor> is TRUE, but no value <Arrhenius Factor> found')
341
END IF
342
END IF
343
Ehf = 1.0_dp
344
EnhcmntFactFlag = ListGetString( Material,'Glen Enhancement Factor Function', UseEUsrf )
345
IF (UseEUsrf) THEN
346
IF (.NOT.PRESENT(LocalIP)) CALL FATAL('EffectiveViscosity',&
347
'Chose "Glen Enhancement Factor Function" but no LocalIP provided by calling function')
348
Fnc = GetProcAddr( EnhcmntFactFlag, Quiet=.TRUE. )
349
EhF = EnhancementFactorUserFunction( Fnc, CurrentModel, Element, Nodes, n, nd, &
350
Basis, dBasisdx, Viscosity, Velo, dVelodx, s , LocalIP)
351
ELSE
352
NodalEhF(1:n) = ListGetReal( Material, 'Glen Enhancement Factor',&
353
n, Element % NodeIndexes, GotIt )
354
IF (GotIt) &
355
EhF = SUM(Basis(1:n) * NodalEhF(1:n))
356
END IF
357
358
IF (PRESENT(muder)) muder = 0.5_dp * ( EhF * ArrheniusFactor)**(-1.0_dp/c2) &
359
* ((1.0_dp/c2)-1.0_dp)/2.0_dp * s**(((1.0_dp/c2)-1.0_dp)/2.0_dp - 1.0_dp)/4.0_dp
360
361
c3n = ListGetReal( Material, 'Critical Shear Rate',n, Element % NodeIndexes,GotIt )
362
IF (GotIt) THEN
363
c3 = SUM( Basis(1:n) * c3n(1:n) )
364
IF(s < c3**2) THEN
365
s = c3**2
366
IF (PRESENT(muder)) muder = 0._dp
367
END IF
368
END IF
369
370
! compute the effective viscosity
371
mu = 0.5_dp * (EhF * ArrheniusFactor)**(-1.0_dp/c2) * s**(((1.0_dp/c2)-1.0_dp)/2.0_dp);
372
373
CASE('power law')
374
c2n = ListGetReal( Material, 'Viscosity Exponent', n, Element % NodeIndexes )
375
c2 = SUM( Basis(1:n) * c2n(1:n) )
376
377
s = ss
378
IF (PRESENT(muder)) THEN
379
IF (s /= 0) THEN
380
muder = Viscosity * (c2-1)/2 * s**((c2-1)/2-1)
381
ELSE
382
muder = 0.0_dp
383
END IF
384
END IF
385
386
c3n = ListGetReal( Material, 'Critical Shear Rate',n, Element % NodeIndexes,gotIt )
387
IF (GotIt) THEN
388
c3 = SUM( Basis(1:n) * c3n(1:n) )
389
IF(s < c3**2) THEN
390
s = c3**2
391
IF (PRESENT(muder)) muder = 0._dp
392
END IF
393
END IF
394
mu = Viscosity * s**((c2-1)/2)
395
396
c4n = ListGetReal( Material, 'Nominal Shear Rate',n, Element % NodeIndexes,gotIt )
397
IF (GotIt) THEN
398
c4 = SUM( Basis(1:n) * c4n(1:n) )
399
mu = mu / c4**(c2-1)
400
IF (PRESENT(muder)) muder = muder / c4**(c2-1)
401
END IF
402
403
CASE('power law too')
404
c2n = ListGetReal( Material, 'Viscosity Exponent', n, Element % NodeIndexes )
405
c2 = SUM( Basis(1:n) * c2n(1:n) )
406
mu = Viscosity **(-1/c2)* ss**(-(c2-1)/(2*c2)) / 2
407
IF ( PRESENT(muder) ) muder = &
408
Viscosity**(-1/c2)*(-(c2-1)/(2*c2))*ss*(-(c2-1)/(2*c2)-1) / 2
409
410
CASE ('carreau')
411
c1n = ListGetReal( Material, 'Viscosity Difference',n,Element % NodeIndexes )
412
c1 = SUM( Basis(1:n) * c1n(1:n) )
413
c2n = ListGetReal( Material, 'Viscosity Exponent', n, Element % NodeIndexes )
414
c2 = SUM( Basis(1:n) * c2n(1:n) )
415
c3n = ListGetReal( Material, 'Viscosity Transition',n,Element % NodeIndexes )
416
c3 = SUM( Basis(1:n) * c3n(1:n) )
417
c4 = ListGetConstReal( Material, 'Yasuda Exponent',gotIt)
418
IF(gotIt) THEN
419
s = SQRT(ss)
420
mu = Viscosity + c1 * (1 + c3**c4*ss**(c4/2))**((c2-1)/c4)
421
IF ( PRESENT(muder ) ) muder = &
422
c1*(1+c3**c4*ss**(c4/2))**((c2-1)/c4-1)*(c2-1)/2*c3**c4*ss**(c4/2-1)
423
ELSE
424
mu = Viscosity + c1 * (1 + c3*c3*ss)**((c2-1)/2)
425
IF ( PRESENT(muder) ) muder = &
426
c1*(c2-1)/2*c3**2*(1+c3**2*ss)**((c2-1)/2-1)
427
END IF
428
429
CASE ('cross')
430
c1n = ListGetReal( Material, 'Viscosity Difference',n,Element % NodeIndexes )
431
c1 = SUM( Basis(1:n) * c1n(1:n) )
432
c2n = ListGetReal( Material, 'Viscosity Exponent', n, Element % NodeIndexes )
433
c2 = SUM( Basis(1:n) * c2n(1:n) )
434
c3n = ListGetReal( Material, 'Viscosity Transition',n,Element % NodeIndexes )
435
c3 = SUM( Basis(1:n) * c3n(1:n) )
436
mu = Viscosity + c1 / (1 + c3*ss**(c2/2))
437
IF ( PRESENT(muder) ) muder = &
438
-c1*c3*ss**(c2/2)*c2 / (2*(1+c3*ss**(c2/2))**2*ss)
439
440
CASE ('powell eyring')
441
c1n = ListGetReal( Material, 'Viscosity Difference',n,Element % NodeIndexes)
442
c1 = SUM( Basis(1:n) * c1n(1:n) )
443
c2 = ListGetConstReal( Material, 'Viscosity Transition')
444
s = SQRT(ss)
445
IF(c2*s < 1.0d-5) THEN
446
mu = Viscosity + c1
447
ELSE
448
mu = Viscosity + c1 * LOG(c2*s+SQRT(c2*c2*ss+1))/(c2*s)
449
IF ( PRESENT(muder) ) muder = &
450
c1*(c2/(2*s)+c2**2/(2*SQRT(c2**2*ss+1)))/((c2*s+SQRT(c2*ss+1))*c2*s) - &
451
c1*LOG(c2*s+SQRT(c2**2*ss+1))/(c2*s**3)/2
452
END IF
453
454
CASE( 'smagorinsky' )
455
c2n = ListGetReal( Material, 'Smagorinsky Constant', &
456
n, Element % NodeIndexes,gotit )
457
c2 = SUM( Basis(1:n) * c2n(1:n) )
458
h = ElementDiameter( Element, Nodes )
459
Viscosity = Viscosity + Density * c2 * h**2 * SQRT(2*ss) / 2
460
IF ( PRESENT(muder) ) muder = &
461
Density*c2*h**2*SQRT(2._dp)/(4*SQRT(ss))
462
463
CASE( 'ke','k-epsilon' )
464
IF (ListGetString(Material,'KE Model',gotIt)/='v2-f' ) THEN
465
Var => VariableGet( CurrentModel % Variables, 'Kinetic Energy' )
466
IF ( .NOT. ASSOCIATED( Var ) ) &
467
CALL Fatal( 'Viscosity Model', 'The kinetic energy variable not defined?' )
468
KE_K = SUM(Basis(1:n) * Var % Values(Var % Perm(Element % NodeIndexes)))
469
470
Var => VariableGet( CurrentModel % Variables, 'Kinetic Dissipation' )
471
IF ( .NOT. ASSOCIATED( Var ) ) &
472
CALL Fatal( 'Viscosity Model', 'The kinetic dissipation rate variable not defined?' )
473
KE_E = SUM(Basis(1:n) * Var % Values(Var % Perm(Element % NodeIndexes)))
474
475
Vals(1:n) = ListGetReal( Material, 'KE Cmu',n,Element % NodeIndexes,gotIt )
476
IF ( .NOT. GotIt ) THEN
477
Cmu = SUM( Basis(1:n) * Vals(1:n) )
478
ELSE
479
Cmu = 0.09_dp
480
END IF
481
mu = Viscosity + Cmu*Density*KE_K**2 / KE_E
482
ELSE
483
Var => VariableGet( CurrentModel % Variables, 'Kinetic Energy' )
484
IF ( .NOT. ASSOCIATED( Var ) ) &
485
CALL Fatal( 'Viscosity Model', 'The kinetic energy variable not defined?' )
486
KE_K = SUM(Basis(1:n) * Var % Values(Var % Perm(Element % NodeIndexes)))
487
488
Var => VariableGet( CurrentModel % Variables, 'Kinetic Dissipation' )
489
IF ( .NOT. ASSOCIATED( Var ) ) &
490
CALL Fatal( 'Viscosity Model', 'The kinetic dissipation rate variable not defined?' )
491
KE_E = SUM(Basis(1:n) * Var % Values(Var % Perm(Element % NodeIndexes)))
492
493
Var => VariableGet( CurrentModel % Variables, 'V2' )
494
IF ( .NOT. ASSOCIATED( Var ) ) &
495
CALL Fatal( 'Viscosity Model', 'The V2 variable not defined?' )
496
KE_Z = SUM(Basis(1:n) * Var % Values(Var % Perm(Element % NodeIndexes)))
497
498
Vals(1:n) = ListGetReal( Material, 'V2-F CT',n,Element % NodeIndexes )
499
CT = SUM( Basis(1:n) * Vals(1:n) )
500
TimeScale = MAX( KE_K/KE_E, CT*SQRT(Viscosity/Density/KE_E) )
501
502
Vals(1:n) = ListGetReal( Material, 'KE Cmu',n,Element % NodeIndexes )
503
Cmu = SUM( Basis(1:n) * Vals(1:n) )
504
505
mu = Viscosity + Cmu*Density*KE_Z*TimeScale
506
END IF
507
508
CASE( 'rng k-epsilon' )
509
Var => VariableGet( CurrentModel % Variables, 'Effective Viscosity')
510
mu = SUM( Basis(1:n) * Var % Values( Var % Perm( Element % NodeIndexes )))
511
512
CASE( 'spalart-allmaras' )
513
Var => VariableGet( CurrentModel % Variables, 'Turbulent Viscosity')
514
IF ( .NOT. ASSOCIATED( Var ) ) &
515
CALL Fatal( 'Viscosity Model', 'The turbulent viscosity variable not defined?' )
516
mu = SUM( Basis(1:n) * Var % Values( Var % Perm( Element % NodeIndexes )))
517
c1 = mu/(Viscosity/Density)
518
c1 = c1**3 / (c1**3 + 7.1_dp**3)
519
mu = Viscosity + mu*Density*c1
520
521
CASE( 'k-omega' )
522
Var => VariableGet( CurrentModel % Variables, 'Kinetic Energy' )
523
IF ( .NOT. ASSOCIATED( Var ) ) &
524
CALL Fatal( 'Viscosity Model', 'The kinetic energy variable not defined?' )
525
KE_K = SUM(Basis(1:n) * Var % Values(Var % Perm(Element % NodeIndexes)))
526
527
Var => VariableGet( CurrentModel % Variables, 'Kinetic Dissipation' )
528
IF ( .NOT. ASSOCIATED( Var ) ) &
529
CALL Fatal( 'Viscosity Model', 'The kinetic dissipation rate variable not defined?' )
530
KE_E = SUM(Basis(1:n) * Var % Values(Var % Perm(Element % NodeIndexes)))
531
532
mu = Viscosity + Density * KE_K / KE_E
533
534
CASE( 'sst k-omega' )
535
Var => VariableGet( CurrentModel % Variables, 'Kinetic Energy' )
536
IF ( .NOT. ASSOCIATED( Var ) ) &
537
CALL Fatal( 'Viscosity Model', 'The kinetic energy variable not defined?' )
538
KE_K = SUM(Basis(1:n) * Var % Values(Var % Perm(Element % NodeIndexes)))
539
540
Var => VariableGet( CurrentModel % Variables, 'Kinetic Dissipation' )
541
IF ( .NOT. ASSOCIATED( Var ) ) &
542
CALL Fatal( 'Viscosity Model', 'The kinetic dissipation rate variable not defined?' )
543
KE_E = SUM(Basis(1:n) * Var % Values(Var % Perm(Element % NodeIndexes)))
544
545
Var => VariableGet( CurrentModel % Variables, 'Wall distance' )
546
IF ( .NOT. ASSOCIATED( Var ) ) &
547
CALL Fatal( 'Viscosity Model', 'The wall distance variable not defined?' )
548
Dist = SUM(Basis(1:n) * Var % Values(Var % Perm(Element % NodeIndexes)))
549
550
F2 = TANH( MAX(2*SQRT(KE_K)/(0.09_dp*KE_E*Dist), &
551
500._dp*Viscosity/(Density*KE_E*Dist**2))**2)
552
553
! F3 = 1-TANH((150*Viscosity/Density/KE_E/Dist**2)**4)
554
F3 = 1
555
556
mu = Viscosity+0.31_dp*Density*KE_K/MAX(0.31_dp*KE_E,SQRT(ss)*F2*F3)
557
558
CASE( 'levelset' )
559
TempSol => VariableGet( CurrentModel % Variables, 'Surface' )
560
IF ( ASSOCIATED( TempSol) ) THEN
561
TempPerm => TempSol % Perm
562
Temperature => TempSol % Values
563
ELSE
564
CALL Warn('EffectiveViscosity','variable Surface needed in levelset viscosity model')
565
END IF
566
567
c1n = ListGetReal( Material, 'Viscosity Difference',n,Element % NodeIndexes)
568
c1 = SUM( Basis(1:n) * c1n(1:n) )
569
c2 = ListGetConstReal( Material, 'Levelset bandwidth')
570
571
Temp = SUM(Basis(1:n) * Temperature(TempPerm(Element % NodeIndexes(1:n))))
572
Temp = Temp / c2
573
IF(Temp < -1.0) THEN
574
c3 = 0.0d0
575
ELSE IF(Temp > 1.0) THEN
576
c3 = 1.0d0
577
ELSE
578
c3 = 0.75d0 * (Temp - Temp**3/3) + 0.5d0
579
END IF
580
581
mu = Viscosity + c3 * c1
582
583
CASE( 'user function' )
584
str = ListGetString( Material, 'Viscosity Function' )
585
Fnc = GetProcAddr( str, Quiet=.TRUE. )
586
mu = MaterialUserFunction( Fnc, CurrentModel, Element, Nodes, n, nd, &
587
Basis, dBasisdx, Viscosity, Velo, dVelodx )
588
589
CASE DEFAULT
590
CALL WARN('EffectiveViscosity','Unknown material model')
591
592
END SELECT
593
594
595
! Add a generic temperature coefficient at the integration point
596
! for backward compatibility this is activated by an existing keyword
597
!--------------------------------------------------------------------
598
c1 = ListGetConstReal( Material, 'Viscosity Temp Exp',GotIt)
599
IF( GotIt ) THEN
600
TempSol => VariableGet( CurrentModel % Variables, 'Temperature' )
601
IF ( ASSOCIATED( TempSol) ) THEN
602
TempPerm => TempSol % Perm
603
Temperature => TempSol % Values
604
ELSE
605
CALL Warn('EffectiveViscosity','variable Temperature needed for thermal viscosity model')
606
END IF
607
c2 = ListGetConstReal( Material, 'Viscosity Temp Ref')
608
c3 = ListGetConstReal( Material, 'Viscosity Temp Offset',GotIt)
609
Temp = SUM(Basis(1:n) * Temperature(TempPerm(Element % NodeIndexes(1:n))))
610
TempCoeff = EXP(c1*(1/(Temp+c3)-1/c2))
611
612
mu = TempCoeff * mu
613
END IF
614
615
616
!------------------------------------------------------------------------------
617
END FUNCTION EffectiveViscosity
618
!------------------------------------------------------------------------------
619
620
621
!------------------------------------------------------------------------------
622
!> Returns effective heat conductivity mainly related to turbulence models.
623
!------------------------------------------------------------------------------
624
FUNCTION EffectiveConductivity( Conductivity,Density,Element, &
625
Temperature,Ux,Uy,Uz,Nodes,n,nd,u,v,w ) RESULT(PCond)
626
!------------------------------------------------------------------------------
627
USE ModelDescription
628
629
REAL(KIND=dp) :: Conductivity,Density,u,v,w,PCond, &
630
Ux(:),Uy(:),Uz(:), Temperature(:), NodalViscosity(n)
631
TYPE(Nodes_t) :: Nodes
632
INTEGER :: n,nd
633
TYPE(Element_t),POINTER :: Element
634
635
!------------------------------------------------------------------------------
636
REAL(KIND=dp) :: Basis(nd),dBasisdx(nd,3)
637
LOGICAL :: stat,GotIt
638
INTEGER :: i
639
CHARACTER(:), ALLOCATABLE :: ConductivityFlag
640
TYPE(ValueList_t), POINTER :: Material
641
REAL(KIND=dp) :: x, y, z, c1n(n), Temp(1), dTempdx(3,1), Pr_t, c_p,&
642
mu, Tmu, DetJ
643
644
! Temperature is needed for thermal models
645
TYPE(Variable_t), POINTER :: TempSol
646
647
INTEGER(KIND=AddrInt) :: Fnc
648
CHARACTER(:), ALLOCATABLE :: str
649
!------------------------------------------------------------------------------
650
PCond = Conductivity
651
652
Material => GetMaterial( Element )
653
ConductivityFlag = GetString( Material,'Heat Conductivity Model', GotIt)
654
IF(.NOT. gotIt) RETURN
655
656
!------------------------------------------------------------------------------
657
SELECT CASE( ConductivityFlag )
658
CASE( 'ke','k-epsilon', 'turbulent' )
659
stat = ElementInfo( Element,Nodes,u,v,w,detJ,Basis )
660
661
c1n(1:n) = GetReal( Material, 'Heat Capacity' )
662
c_p = SUM( Basis(1:n) * c1n(1:n) )
663
664
c1n(1:n) = GetReal( Material, 'Viscosity' )
665
mu = SUM( Basis(1:n) * c1n(1:n) )
666
667
c1n(1:n) = GetReal( Material, 'Turbulent Prandtl Number',GotIt )
668
IF ( GotIt ) THEN
669
Pr_t = SUM( Basis(1:n) * c1n(1:n) )
670
ELSE
671
Pr_t = 0.85_dp
672
END IF
673
674
Tmu = EffectiveViscosity( mu,Density,Ux,Uy,Uz,Element, &
675
Nodes,n,nd,u,v,w ) - mu
676
PCond = Conductivity + c_p * Tmu / Pr_t
677
678
CASE( 'user function' )
679
str = ListGetString( Material, 'Heat Conductivity Function' )
680
Fnc = GetProcAddr( str, Quiet=.TRUE. )
681
682
stat = ElementInfo( Element,Nodes,u,v,w, detJ, Basis,dBasisdx )
683
Temp(1) = SUM( Basis(1:nd) * Temperature(1:nd) )
684
DO i=1,3
685
dTempdx(i,1) = SUM( dBasisdx(1:nd,i) * Temperature(1:nd) )
686
END DO
687
688
PCond = MaterialUserFunction( Fnc, CurrentModel, Element, Nodes, n, nd, &
689
Basis, dBasisdx, Conductivity, Temp, dTempdx )
690
691
CASE DEFAULT
692
CALL WARN('EffectiveConductivity','Unknown material model')
693
694
END SELECT
695
!------------------------------------------------------------------------------
696
697
END FUNCTION EffectiveConductivity
698
!------------------------------------------------------------------------------
699
700
701
702
!------------------------------------------------------------------------------
703
!> Returns density stemming from various equations of state.
704
!------------------------------------------------------------------------------
705
SUBROUTINE ElementDensity( Density, n )
706
!------------------------------------------------------------------------------
707
INTEGER :: n
708
REAL(KIND=dp) :: Density(:)
709
!------------------------------------------------------------------------------
710
REAL(KIND=dp) :: HeatCapacity(n), SpecificHeatRatio, GasConstant(n), &
711
ReferencePressure, Pressure(n), Temperature(n), ReferenceTemperature(n), &
712
HeatExpansionCoeff(n)
713
LOGICAL :: Found
714
TYPE(ValueList_t), POINTER :: Material
715
716
Material => GetMaterial()
717
718
SELECT CASE( GetString( Material, 'Compressibility Model', Found) )
719
CASE( 'perfect gas', 'ideal gas' )
720
HeatCapacity(1:n) = GetReal( Material, 'Heat Capacity' )
721
SpecificHeatRatio = ListGetConstReal( Material, &
722
'Specific Heat Ratio', Found )
723
IF ( .NOT.Found ) SpecificHeatRatio = 5.d0/3.d0
724
725
GasConstant(1:n) = ( SpecificHeatRatio - 1.d0 ) * &
726
HeatCapacity(1:n) / SpecificHeatRatio
727
728
ReferencePressure = GetCReal( Material, 'Reference Pressure', Found )
729
IF ( .NOT.Found ) ReferencePressure = 0.0d0
730
731
CALL GetScalarLocalSolution( Pressure, 'Pressure' )
732
CALL GetScalarLocalSolution( Temperature, 'Temperature' )
733
734
Density(1:n) = ( Pressure(1:n) + ReferencePressure ) / &
735
( GasConstant(1:n) * Temperature(1:n) )
736
737
CASE( 'thermal' )
738
HeatExpansionCoeff(1:n) = GetReal( Material, &
739
'Heat Expansion Coefficient' )
740
741
ReferenceTemperature(1:n) = GetReal( Material, &
742
'Reference Temperature' )
743
CALL GetScalarLocalSolution( Temperature, 'Temperature' )
744
745
Density(1:n) = GetReal( Material,'Density' )
746
Density(1:n) = Density(1:n) * ( 1 - HeatExpansionCoeff(1:n) * &
747
( Temperature(1:n) - ReferenceTemperature(1:n) ) )
748
749
CASE( 'user defined' )
750
CALL GetScalarLocalSolution( Density, 'Density' )
751
752
CASE DEFAULT
753
Density(1:n) = GetReal( Material, 'Density' )
754
END SELECT
755
END SUBROUTINE ElementDensity
756
757
END MODULE MaterialModels
758
759
!> \} ElmerLib
760
761