Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/fem/tests/AdvReactDG_P/AdvReactDG_P.F90
3206 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 program is free software; you can redistribute it and/or
8
! * modify it under the terms of the GNU General Public License
9
! * as published by the Free Software Foundation; either version 2
10
! * of the License, or (at your option) any later version.
11
! *
12
! * This program 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
15
! * GNU General Public License for more details.
16
! *
17
! * You should have received a copy of the GNU General Public License
18
! * along with this program (in file fem/GPL-2); if not, write to the
19
! * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20
! * Boston, MA 02110-1301, USA.
21
! *
22
! *****************************************************************************
23
!
24
!******************************************************************************
25
! *
26
! * Authors: Mikko, Lyly, 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: 04 Apr 2004
34
! *
35
! ****************************************************************************
36
37
!------------------------------------------------------------------------------
38
!> Advection-reaction equation solver for scalar fields with discontinuous Galerkin method.
39
!> \ingroup Solvers
40
!------------------------------------------------------------------------------
41
SUBROUTINE AdvectionReactionSolver( Model,Solver,dt,Transient )
42
!------------------------------------------------------------------------------
43
USE DefUtils
44
45
IMPLICIT NONE
46
!------------------------------------------------------------------------------
47
TYPE(Model_t) :: Model !< All model information (mesh, materials, BCs, etc...)
48
TYPE(Solver_t), TARGET :: Solver !< Linear & nonlinear equation solver options
49
REAL(KIND=dp) :: dt !< Timestep size for time dependent simulations
50
LOGICAL :: Transient !< Steady state or transient simulation
51
!------------------------------------------------------------------------------
52
! Local variables
53
!------------------------------------------------------------------------------
54
TYPE(ValueList_t), POINTER :: BC, BodyForce, Material,&
55
Equation, Constants, SolverParams
56
57
TYPE(Element_t), POINTER :: Element, Face, &
58
ParentElement, P1, P2
59
60
LOGICAL :: AllocationsDone = .FALSE., Found, Stat, &
61
LimitSolution, FoundLowerLimit, FoundUpperLimit
62
INTEGER :: Active, DIM,NonLinearIterMin,NonlinearIterMax,iter,&
63
CorrectedLowerLimit,CorrectedUpperLimit
64
INTEGER :: n1,nd1,nd2,n2, k, n, nd,t, istat, i, j, dummyInt, NumberOfFAces, Indexes(128)
65
REAL(KIND=dp) :: Norm,RelativeChange,at,at0,totat,st,totst,&
66
OriginalValue
67
REAL(KIND=dp), ALLOCATABLE :: MASS(:,:), STIFF(:,:), LOAD(:), &
68
FORCE(:), Velo(:,:), MeshVelo(:,:), Gamma(:), Ref(:), &
69
UpperLimit(:), LowerLimit(:)
70
TYPE(Mesh_t), POINTER :: Mesh
71
TYPE(Variable_t), POINTER :: Var
72
CHARACTER(LEN=MAX_NAME_LEN) :: VariableName, SolverName, ExpVariableName
73
74
SAVE MASS, STIFF, LOAD, FORCE, Velo, MeshVelo, Gamma, &
75
AllocationsDone, DIM, VariableName, SolverName, &
76
UpperLimit, LowerLimit
77
!*******************************************************************************
78
79
TYPE( Element_t ), POINTER :: Faces(:)
80
TYPE(Nodes_t) :: ElementNodes
81
82
INTEGER :: DOFs
83
!*******************************************************************************
84
SolverName = 'AdvectionReaction ('// TRIM(Solver % Variable % Name) // ')'
85
VariableName = TRIM(Solver % Variable % Name)
86
WRITE(Message,'(A,A)')&
87
'AdvectionReactionSolver for variable ', VariableName
88
CALL INFO(SolverName,Message,Level=1)
89
90
Mesh => GetMesh()
91
92
IF ( CoordinateSystemDimension() == 2 ) THEN
93
Faces => Mesh % Edges
94
NumberOfFaces = Mesh % NumberOfEdges
95
ELSE
96
Faces => Mesh % Faces
97
NumberOfFaces = Mesh % NumberOfFaces
98
END IF
99
100
! Initialize & allocate some permanent storage, this is done first time only:
101
!----------------------------------------------------------------------------
102
IF ( .NOT. AllocationsDone ) THEN
103
104
N = 2 * MAX(Mesh % MaxElementDOFs, Mesh % MaxElementNodes )
105
ALLOCATE( FORCE(N), MASS(n,n), STIFF(N,N), LOAD(N), &
106
Velo(3,N), MeshVelo( 3,N ), Gamma(n), &
107
UpperLimit(n), LowerLimit(n), STAT = istat )
108
109
IF ( istat /= 0 ) THEN
110
CALL FATAL(SolverName,'Memory allocation error.' )
111
ELSE
112
CALL INFO(SolverName,'Memory allocation done',Level=1 )
113
END IF
114
DIM = CoordinateSystemDimension()
115
AllocationsDone = .TRUE.
116
END IF
117
118
!------------------------------------------------------------------------------
119
! Read physical and numerical constants and initialize
120
!------------------------------------------------------------------------------
121
Constants => GetConstants()
122
SolverParams => GetSolverParams()
123
124
NonlinearIterMax = GetInteger( SolverParams, &
125
'Nonlinear System Max Iterations', Found )
126
IF ( .NOT.Found ) THEN
127
CALL WARN(SolverName,'No > Nonlinear System Max Iterations < found. Setting 1')
128
NonlinearIterMax = 1
129
END IF
130
131
NonlinearIterMin = GetInteger( SolverParams, &
132
'Nonlinear System Min Iterations', Found )
133
IF ( .NOT.Found ) THEN
134
CALL WARN(SolverName,'No >Nonlinear System Min Iterations< found. Setting 1')
135
NonlinearIterMin = 1
136
ELSE IF (NonlinearIterMin > NonlinearIterMax) THEN
137
CALL WARN(SolverName,&
138
'>Nonlinear System Min Iterations< is exceeding >Nonlinear System Max Iterations<.')
139
CALL WARN(SolverName,&
140
'First is being reset to the latter.')
141
NonlinearIterMin = NonlinearIterMax
142
END IF
143
144
ExpVariableName = GetString(SolverParams , 'Exported Variable 1', Found )
145
IF (.NOT.Found) &
146
CALL FATAL(SolverName,'No value > Exported Variable 1 < found in Solver')
147
148
!------------------------------------------------------------------------------
149
! non-linear system iteration loop
150
!------------------------------------------------------------------------------
151
totat = 0; totst = 0
152
DO iter=1,NonlinearIterMax
153
! Assembly of the bulk elements:
154
!-------------------------------
155
!------------------------------------------------------------------------------
156
! print out some information
157
!------------------------------------------------------------------------------
158
at = CPUTime()
159
at0 = RealTime()
160
161
CALL Info( SolverName, ' ', Level=4 )
162
CALL Info( SolverName, ' ', Level=4 )
163
CALL Info( SolverName, '-------------------------------------',Level=4 )
164
WRITE( Message,'(A,I3,A,I3)') &
165
'Nonlinear iteration no.', iter,' of max',NonlinearIterMax
166
CALL Info( SolverName, Message, Level=4 )
167
CALL Info( SolverName, '-------------------------------------',Level=4 )
168
CALL Info( SolverName, ' ', Level=4 )
169
CALL Info( SolverName, 'Starting Assembly...', Level=4 )
170
171
172
CALL DefaultInitialize()
173
Active = GetNOFActive()
174
DO t = 1, Active
175
!------------------------------------------------------------------------------
176
! write some info on status of assembly
177
!------------------------------------------------------------------------------
178
IF ( RealTime() - at0 > 1.0 ) THEN
179
! WRITE(Message,'(a,i3,a)' ) ' Assembly: ', INT(100.0 - 100.0 * &
180
! (Active-t) / &
181
! (1.0*Active)), ' % done'
182
!
183
! CALL Info( SolverName, Message, Level=5 )
184
185
at0 = RealTime()
186
END IF
187
!------------------------------------------------------------------------------
188
! assign pointers and get number of nodes in element
189
!------------------------------------------------------------------------------
190
Element => GetActiveElement(t)
191
n = GetElementNOfNodes(Element)
192
nd = GetElementNOfDOFs(Element)
193
194
Material => GetMaterial(Element)
195
Equation => GetEquation(Element)
196
BodyForce => GetBodyForce(Element)
197
198
!------------------------------------------------------------------------------
199
LOAD(1:n) = GetReal( BodyForce, TRIM(VariableName) // ' Source', Found )
200
201
!------------------------------------------------------------------------------
202
! Get convection and mesh velocity
203
CALL GetLocalALEVelocity(Velo,MeshVelo,SolverName,Material,&
204
Equation,Solver,Model,Element)
205
206
!--------------------------
207
! get reaction coefficient
208
!--------------------------
209
Gamma(1:n) = GetReal( Material, TRIM(VariableName)//' Gamma', Found )
210
211
CALL LocalMatrix(MASS, STIFF, FORCE, LOAD, Velo, Gamma, Element, n,nd)
212
IF ( Transient ) CALL Default1stOrderTime(MASS, STIFF, FORCE)
213
CALL DefaultUpdateEquations(STIFF, FORCE)
214
END DO
215
216
217
! Assembly of the face terms:
218
!----------------------------
219
FORCE = 0.0_dp
220
DO t=1,NumberOfFaces
221
Face => Faces(t)
222
IF ( .NOT. ActiveBoundaryElement(Face) ) CYCLE
223
224
P1 => Face % BoundaryInfo % Left
225
P2 => Face % BoundaryInfo % Right
226
IF ( ASSOCIATED(P2) .AND. ASSOCIATED(P1) ) THEN
227
n = GetElementNOFNodes(Face)
228
n1 = GetElementNOFNodes(P1)
229
n2 = GetElementNOFNodes(P2)
230
231
nd = GetElementNOFDOFs(Face)
232
nd1 = GetElementNOFDOFs(P1)
233
nd2 = GetElementNOFDOFs(P2)
234
235
!------------------------------------------------------------------------------
236
! Get convection and mesh velocity
237
!------------------------------------------------------------------------------
238
Material => GetMaterial(P1)
239
Equation => GetEquation(P1)
240
CALL GetLocalALEVelocity(Velo,MeshVelo,SolverName,Material,&
241
Equation,Solver,Model,Face)
242
243
CALL LocalJumps( STIFF,Face,n,nd,P1,n1,nd1,P2,n2,nd2,Velo )
244
CALL DefaultUpdateEquations( STIFF, FORCE, Face )
245
END IF
246
END DO
247
248
! Loop over the boundary elements:
249
!---------------------------------
250
DO t=1,Mesh % NumberOfBoundaryElements
251
Element => GetBoundaryElement(t)
252
IF( .NOT. ActiveBoundaryElement() ) CYCLE
253
IF( GetElementFamily(Element) < dim ) CYCLE
254
255
ParentElement => Element % BoundaryInfo % Left
256
IF ( .NOT. ASSOCIATED( ParentElement ) ) &
257
ParentElement => Element % BoundaryInfo % Right
258
259
n1 = GetElementNOFnodes(ParentElement)
260
n = GetElementNOFNodes(Element)
261
262
nd = GetElementNOFDOFs(Element)
263
nd1 = GetElementNOFDOFs(ParentElement)
264
!------------------------------------------------------------------------------
265
! Get convection and mesh velocity
266
!------------------------------------------------------------------------------
267
Material => GetMaterial(ParentElement)
268
Equation => GetEquation(ParentElement)
269
CALL GetLocalALEVelocity(Velo,MeshVelo,SolverName,Material,&
270
Equation,Solver,Model,Element)
271
272
BC => GetBC()
273
LOAD = 0.0_dp
274
Found = .FALSE.
275
IF ( ASSOCIATED(BC) ) THEN
276
LOAD(1:n) = GetReal(BC, Solver % Variable % Name, Found)
277
END IF
278
279
MASS = 0.0_dp
280
CALL LocalMatrixBoundary( STIFF, FORCE, LOAD, &
281
Element, n, nd, ParentElement, n1, nd1, Velo, Found )
282
283
IF ( Transient ) CALL Default1stOrderTime(MASS, STIFF, FORCE)
284
CALL DefaultUpdateEquations(STIFF, FORCE)
285
END DO
286
287
CALL DefaultFinishAssembly()
288
CALL Info( SolverName, 'Assembly done', Level=4 )
289
290
!------------------------------------------------------------------------------
291
! Solve the system and check for convergence
292
!------------------------------------------------------------------------------
293
at = CPUTime() - at
294
st = CPUTime()
295
296
! Solve the system:
297
!------------------
298
Norm = DefaultSolve()
299
300
st = CPUTIme()-st
301
totat = totat + at
302
totst = totst + st
303
WRITE(Message,'(a,i4,a,F8.2,F8.2)') 'iter: ',iter,' Assembly: (s)', at, totat
304
CALL Info( SolverName, Message, Level=4 )
305
WRITE(Message,'(a,i4,a,F8.2,F8.2)') 'iter: ',iter,' Solve: (s)', st, totst
306
CALL Info( SolverName, Message, Level=4 )
307
308
RelativeChange = Solver % Variable % NonlinChange
309
310
IF ( Solver % Variable % NonlinConverged == 1 ) THEN
311
WRITE(Message,'(A,I6,A,I6,A)') &
312
'Nonlinear iteration converged after ', iter, &
313
' out of max ',NonlinearIterMax,' iterations'
314
CALL INFO(SolverName,Message)
315
EXIT
316
ELSE IF ((iter .EQ. NonlinearIterMax) .AND. (NonlinearIterMax > 1)) THEN
317
CALL WARN(SolverName,'Maximum nonlinear iterations reached, but system not converged')
318
END IF
319
320
!-----------------------------------------------
321
END DO ! End of nonlinear iteration loop
322
!----------------------------------------------
323
324
325
! Average the elemental results to nodal values:
326
!-----------------------------------------------
327
Var => VariableGet( Mesh % Variables,TRIM(ExpVariableName))
328
IF ( ASSOCIATED( Var ) ) THEN
329
n1 = Mesh % NumberOfNodes
330
ALLOCATE( Ref(n1) )
331
Ref = 0
332
Var % Type = Variable_on_nodes
333
334
IF ( ASSOCIATED( Var % Perm, Solver % Variable % Perm ) ) THEN
335
ALLOCATE( Var % Perm(SIZE(Solver % Variable % Perm)) )
336
Var % Perm = 0
337
DO i = 1,n1
338
Var % Perm(i) = i
339
END DO
340
END IF
341
342
Var % Values = 0.0d0
343
DO t=1,Active
344
Element => GetActiveElement(t)
345
n = GetElementDOFs(Indexes)
346
n = GetElementNOFNodes()
347
DO i=1,n
348
k = Element % NodeIndexes(i)
349
Var % Values(k) = Var % Values(k) + &
350
Solver % Variable % Values( Solver % Variable % Perm(Indexes(i)) )
351
Ref(k) = Ref(k) + 1
352
END DO
353
END DO
354
355
WHERE( Ref > 0 )
356
Var % Values(1:n1) = Var % Values(1:n1) / Ref
357
END WHERE
358
DEALLOCATE( Ref )
359
ELSE
360
WRITE(Message,'(A,A,A)') 'Exported Variable >',TRIM(VariableName) // 'Nodal Result','< not found'
361
CALL FATAL(SolverName,Message)
362
END IF
363
364
CONTAINS
365
366
!------------------------------------------------------------------------------
367
SUBROUTINE LocalMatrix(MASS, STIFF, FORCE, LOAD, Velo, Gamma, Element, n,nd)
368
!------------------------------------------------------------------------------
369
REAL(KIND=dp) :: MASS(:,:), STIFF(:,:), FORCE(:), &
370
LOAD(:), Velo(:,:), Gamma(:)
371
INTEGER :: n,nd
372
TYPE(Element_t), POINTER :: Element
373
!------------------------------------------------------------------------------
374
REAL(KIND=dp) :: Basis(nd),dBasisdx(nd,3)
375
REAL(KIND=dp) :: detJ,U,V,W,S,A,L,cu(3),g
376
LOGICAL :: Stat
377
INTEGER :: i,p,q,t,dim
378
TYPE(GaussIntegrationPoints_t) :: IntegStuff
379
TYPE(Nodes_t), SAVE :: Nodes
380
!------------------------------------------------------------------------------
381
dim = CoordinateSystemDimension()
382
383
FORCE = 0.0_dp
384
STIFF = 0.0_dp
385
MASS = 0.0_dp
386
387
CALL GetElementNodes(Nodes, Element)
388
!------------------------------------------------------------------------------
389
! Numerical integration
390
!------------------------------------------------------------------------------
391
IntegStuff = GaussPoints(Element)
392
393
DO t=1,IntegStuff % n
394
U = IntegStuff % u(t)
395
V = IntegStuff % v(t)
396
W = IntegStuff % w(t)
397
S = IntegStuff % s(t)
398
!------------------------------------------------------------------------------
399
! Basis function values & derivatives at the integration point
400
!------------------------------------------------------------------------------
401
stat = ElementInfo( Element, Nodes, U, V, W, detJ, &
402
Basis, dBasisdx )
403
404
S = S * detJ
405
L = SUM( LOAD(1:n) * Basis(1:n) )
406
g = SUM( Basis(1:n) * Gamma(1:n) )
407
408
cu = 0.0_dp
409
DO i=1,dim
410
cu(i) = SUM(Basis(1:n) * Velo(i,1:n))
411
END DO
412
!------------------------------------------------------------------------------
413
! The advection-reaction equation: dc/dt + grad(u . c) + gamma c = s
414
!------------------------------------------------------------------------------
415
DO p=1,nd
416
DO q=1,nd
417
MASS(p,q) = MASS(p,q) + s * Basis(q) * Basis(p)
418
STIFF(p,q) = STIFF(p,q) + s * g * Basis(q) * Basis(p)
419
DO i=1,dim
420
STIFF(p,q) = STIFF(p,q) - s * cu(i) * Basis(q) * dBasisdx(p,i)
421
END DO
422
END DO
423
END DO
424
FORCE(1:nd) = FORCE(1:nd) + s*L*Basis(1:nd)
425
!------------------------------------------------------------------------------
426
END DO
427
!------------------------------------------------------------------------------
428
END SUBROUTINE LocalMatrix
429
!------------------------------------------------------------------------------
430
431
432
!------------------------------------------------------------------------------
433
SUBROUTINE LocalJumps(STIFF,Face,n,nd,P1,n1,nd1,P2,n2,nd2,Velo)
434
!------------------------------------------------------------------------------
435
IMPLICIT NONE
436
REAL(KIND=dp) :: STIFF(:,:), Velo(:,:)
437
INTEGER :: n,n1,n2,nd,nd1,nd2
438
TYPE(Element_t), POINTER :: Face, P1, P2
439
!------------------------------------------------------------------------------
440
REAL(KIND=dp) :: Basis(nd),P1Basis(nd1),P2Basis(nd2)
441
REAL(KIND=dp) :: Jump(nd1+nd2), Average(nd1+nd2)
442
REAL(KIND=dp) :: detJ, U, V, W, S, Udotn, xx, yy
443
LOGICAL :: Stat
444
INTEGER :: i, j, p, q, dim, t, nFace, nParent
445
TYPE(GaussIntegrationPoints_t) :: IntegStuff
446
REAL(KIND=dp) :: Normal(3), cu(3), LeftOut(3)
447
448
TYPE(Nodes_t), SAVE :: FaceNodes, P1Nodes, P2Nodes
449
!------------------------------------------------------------------------------
450
dim = CoordinateSystemDimension()
451
STIFF = 0.0_dp
452
453
CALL GetElementNodes(P1Nodes, P1)
454
CALL GetElementNodes(P2Nodes, P2)
455
CALL GetElementNodes(FaceNodes, Face)
456
!------------------------------------------------------------------------------
457
! Numerical integration over the edge
458
!------------------------------------------------------------------------------
459
IntegStuff = GaussPoints(Face)
460
461
LeftOut(1) = SUM(P1Nodes % x(1:n1)) / n1
462
LeftOut(2) = SUM(P1Nodes % y(1:n1)) / n1
463
LeftOut(3) = SUM(P1Nodes % z(1:n1)) / n1
464
LeftOut(1) = SUM(FaceNodes % x(1:n)) / n - LeftOut(1)
465
LeftOut(2) = SUM(FaceNodes % y(1:n)) / n - LeftOut(2)
466
LeftOut(3) = SUM(FaceNodes % z(1:n)) / n - LeftOut(3)
467
468
DO t=1,IntegStuff % n
469
U = IntegStuff % u(t)
470
V = IntegStuff % v(t)
471
W = IntegStuff % w(t)
472
S = IntegStuff % s(t)
473
474
! Basis function values & derivatives at the integration point:
475
!--------------------------------------------------------------
476
stat = ElementInfo(Face, FaceNodes, U, V, W, detJ,Basis)
477
S = S * detJ
478
479
Normal = NormalVector(Face, FaceNodes, U, V, .FALSE.)
480
IF (SUM(LeftOut*Normal)<0) Normal = -Normal
481
482
! Find basis functions for the parent elements:
483
! ---------------------------------------------
484
CALL FindParentUVW(Face,n,P1,n1,U,V,W,Basis)
485
stat = ElementInfo(P1, P1Nodes, U, V, W, detJ, P1Basis)
486
487
CALL FindParentUVW(Face,n,P2,n2,U,V,W,Basis)
488
stat = ElementInfo(P2, P2Nodes, U, V, W, detJ, P2Basis)
489
490
! Integrate jump terms:
491
! ---------------------
492
Jump(1:nd1) = P1Basis(1:nd1)
493
Jump(nd1+1:nd1+nd2) = -P2Basis(1:nd2)
494
495
Average(1:nd1) = P1Basis(1:nd1) / 2
496
Average(nd1+1:nd1+nd2) = P2Basis(1:nd2) / 2
497
498
cu = 0.0_dp
499
DO i=1,dim
500
cu(i) = SUM( Velo(i,1:n) * Basis(1:n) )
501
END DO
502
Udotn = SUM( Normal * cu )
503
504
DO p=1,nd1+nd2
505
DO q=1,nd1+nd2
506
STIFF(p,q) = STIFF(p,q) + s * Udotn * Average(q) * Jump(p)
507
STIFF(p,q) = STIFF(p,q) + s * ABS(Udotn)/2 * Jump(q) * Jump(p)
508
END DO
509
END DO
510
END DO
511
!------------------------------------------------------------------------------
512
END SUBROUTINE LocalJumps
513
!------------------------------------------------------------------------------
514
515
516
517
!------------------------------------------------------------------------------
518
SUBROUTINE LocalMatrixBoundary( STIFF, FORCE, LOAD, &
519
Element, n, nd, ParentElement, np, npd,Velo, InFlowBC )
520
!------------------------------------------------------------------------------
521
REAL(KIND=dp) :: STIFF(:,:), FORCE(:), LOAD(:), Velo(:,:)
522
INTEGER :: n, np,nd,npd
523
LOGICAL :: InFlowBC
524
TYPE(Element_t), POINTER :: Element, ParentElement
525
!------------------------------------------------------------------------------
526
REAL(KIND=dp) :: Basis(nd), ParentBasis(npd)
527
INTEGER :: i,j,k,m,p,q,t,dim
528
529
REAL(KIND=dp) :: Normal(3), g, L, Udotn, cu(3), detJ,U,V,W,S
530
LOGICAL :: Stat, Inflow
531
TYPE(GaussIntegrationPoints_t) :: IntegStuff
532
533
TYPE(Nodes_t) :: Nodes, ParentNodes
534
!------------------------------------------------------------------------------
535
dim = CoordinateSystemDimension()
536
FORCE = 0.0_dp
537
STIFF = 0.0_dp
538
539
CALL GetElementNodes(Nodes, Element)
540
CALL GetElementNodes(ParentNodes, ParentElement)
541
542
Normal = NormalVector( Element, Nodes, 0.0_dp, 0.0_dp, .TRUE. )
543
DO i=1,3
544
cu(i) = SUM(Velo(i,1:n)) / n
545
END DO
546
Inflow = InFlowBC .AND. SUM( Normal * cu ) < 0.0_dp
547
548
! Numerical integration:
549
!-----------------------
550
IntegStuff = GaussPoints(Element)
551
552
DO t=1,IntegStuff % n
553
U = IntegStuff % u(t)
554
V = IntegStuff % v(t)
555
W = IntegStuff % w(t)
556
S = IntegStuff % s(t)
557
558
Normal = NormalVector(Element, Nodes, U, V, .TRUE.)
559
560
! Basis function values & derivatives at the integration point:
561
! -------------------------------------------------------------
562
stat = ElementInfo(Element, Nodes, U, V, W, detJ,Basis)
563
S = S * detJ
564
565
CALL FindParentUVW(Element, n, ParentElement, np, U, V, W, Basis)
566
stat = ElementInfo( ParentElement, ParentNodes, U, V, W, &
567
detJ, ParentBasis)
568
569
L = SUM(LOAD(1:n) * Basis(1:n))
570
cu = 0.0_dp
571
DO i=1,dim
572
cu(i) = SUM(Velo(i,1:n) * Basis(1:n))
573
END DO
574
Udotn = SUM(Normal*cu)
575
576
DO p = 1,npd
577
IF ( Inflow ) THEN
578
FORCE(p) = FORCE(p) - s*Udotn*L*ParentBasis(p)
579
ELSE
580
DO q=1,npd
581
STIFF(p,q) = STIFF(p,q) + s*Udotn*ParentBasis(q)*ParentBasis(p)
582
END DO
583
END IF
584
END DO
585
END DO
586
!------------------------------------------------------------------------------
587
END SUBROUTINE LocalMatrixBoundary
588
!------------------------------------------------------------------------------
589
!
590
!------------------------------------------------------------------------------
591
SUBROUTINE GetLocalALEVelocity(Velo,MeshVelo,SolverName,Material,&
592
Equation,Solver,Model,Element)
593
IMPLICIT NONE
594
!------------------------------------------------------------------------------
595
REAL (KIND=dp) :: Velo(:,:), MeshVelo(:,:)
596
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName
597
TYPE(ValueList_t), POINTER :: Material,Equation
598
TYPE(Solver_t), TARGET :: Solver
599
TYPE(Model_t), TARGET :: Model
600
TYPE(Element_t),POINTER :: Element
601
!------------------------------------------------------------------------------
602
CHARACTER(LEN=MAX_NAME_LEN) :: ConvectionFlag, FlowSolName
603
INTEGER :: i,j,k,N,FlowDOFs
604
INTEGER, POINTER :: FlowPerm(:)
605
REAL(KIND=dp), POINTER :: FlowSolution(:)
606
TYPE(Variable_t), POINTER :: FlowSol
607
LOGICAL :: Found
608
!------------------------------------------------------------------------------
609
n = GetElementNOFNodes( Element )
610
ConvectionFlag = GetString( Equation, 'Convection', Found )
611
IF (.NOT. Found) &
612
CALL FATAL(SolverName, 'No string for keyword >Convection< found in Equation')
613
Velo = 0.0d00
614
! constant (i.e., in section Material given) velocity
615
!---------------------------------------------------
616
IF ( ConvectionFlag == 'constant' ) THEN
617
Velo(1,1:N) = GetReal( Material, 'Convection Velocity 1', Found, Element )
618
IF (.NOT.Found) Velo(1,1:N) = 0.0d0
619
Velo(2,1:N) = GetReal( Material, 'Convection Velocity 2', Found, Element )
620
IF (.NOT.Found) Velo(2,1:N) = 0.0d0
621
Velo(3,1:N) = GetReal( Material, 'Convection Velocity 3', Found, Element )
622
IF (.NOT.Found) Velo(3,1:N) = 0.0d0
623
! computed velocity
624
!------------------Equation => GetEquation()
625
ELSE IF (ConvectionFlag == 'computed' ) THEN
626
FlowSolName = GetString( Equation,'Flow Solution Name', Found)
627
IF(.NOT.Found) THEN
628
CALL WARN(SolverName,'Keyword >Flow Solution Name< not found in section >Equation<')
629
CALL WARN(SolverName,'Taking default value >Flow Solution<')
630
WRITE(FlowSolName,'(A)') 'Flow Solution'
631
END IF
632
FlowSol => VariableGet( Solver % Mesh % Variables, FlowSolName )
633
IF ( ASSOCIATED( FlowSol ) ) THEN
634
FlowPerm => FlowSol % Perm
635
FlowDOFs = FlowSol % DOFs
636
FlowSolution => FlowSol % Values
637
ELSE
638
WRITE(Message,'(A,A,A)') &
639
'Convection flag set to >computed<, but no variable >',FlowSolName,'< found'
640
CALL FATAL(SolverName,Message)
641
END IF
642
643
644
DO i=1,n
645
k = FlowPerm(Element % NodeIndexes(i))
646
IF ( k > 0 ) THEN
647
! Pressure = FlowSolution(FlowDOFs*k)
648
649
SELECT CASE( FlowDOFs )
650
CASE(2)
651
Velo(1,i) = FlowSolution( FlowDOFs*k-1 )
652
Velo(2,i) = 0.0d0
653
Velo(3,i) = 0.0d0
654
CASE(3)
655
Velo(1,i) = FlowSolution( FlowDOFs*k-2 )
656
Velo(2,i) = FlowSolution( FlowDOFs*k-1 )
657
Velo(3,i) = 0.0d0
658
CASE(4)
659
Velo(1,i) = FlowSolution( FlowDOFs*k-3 )
660
Velo(2,i) = FlowSolution( FlowDOFs*k-2 )
661
Velo(3,i) = FlowSolution( FlowDOFs*k-1 )
662
END SELECT
663
END IF
664
END DO
665
ELSE IF (ConvectionFlag == 'none' ) THEN
666
Velo = 0.0d0
667
ELSE
668
WRITE(Message,'(A,A,A)') 'Convection flag >', ConvectionFlag ,'< not recognised'
669
CALL FATAL(SolverName,Message)
670
END IF
671
!-------------------------------------------------
672
! Add mesh velocity (if any) for ALE formulation
673
!-------------------------------------------------
674
MeshVelo = 0.0d0
675
CALL GetVectorLocalSolution( MeshVelo, 'Mesh Velocity', Element)
676
IF (ANY( MeshVelo /= 0.0d0 )) THEN
677
DO i=1,FlowDOFs
678
Velo(i,1:N) = Velo(i,1:N) - MeshVelo(i,1:N)
679
END DO
680
END IF
681
END SUBROUTINE GetLocalALEVelocity
682
683
!------------------------------------------------------------------------------
684
END SUBROUTINE AdvectionReactionSolver
685
!------------------------------------------------------------------------------
686
687