Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/fem/src/Lists.F90
5241 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
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: 02 Jun 1997
34
! *
35
! *****************************************************************************/
36
37
!> \ingroup ElmerLib
38
!> \{
39
40
!------------------------------------------------------------------------------
41
!> List handling utilities. In Elmer all the keywords are saved to a list,
42
!> and later accessed from it repeatedly. Therefore these subroutines are
43
!> essential in Elmer programming.
44
!------------------------------------------------------------------------------
45
#include "../config.h"
46
47
MODULE Lists
48
49
USE GeneralUtils
50
51
IMPLICIT NONE
52
53
INTEGER, PARAMETER :: LIST_TYPE_LOGICAL = 1
54
INTEGER, PARAMETER :: LIST_TYPE_STRING = 2
55
INTEGER, PARAMETER :: LIST_TYPE_INTEGER = 3
56
INTEGER, PARAMETER :: LIST_TYPE_CONSTANT_SCALAR = 4
57
INTEGER, PARAMETER :: LIST_TYPE_VARIABLE_SCALAR = 5
58
INTEGER, PARAMETER :: LIST_TYPE_CONSTANT_SCALAR_STR = 6
59
INTEGER, PARAMETER :: LIST_TYPE_VARIABLE_SCALAR_STR = 7
60
INTEGER, PARAMETER :: LIST_TYPE_CONSTANT_SCALAR_PROC = 8
61
INTEGER, PARAMETER :: LIST_TYPE_CONSTANT_TENSOR = 9
62
INTEGER, PARAMETER :: LIST_TYPE_VARIABLE_TENSOR = 10
63
INTEGER, PARAMETER :: LIST_TYPE_CONSTANT_TENSOR_STR = 11
64
INTEGER, PARAMETER :: LIST_TYPE_VARIABLE_TENSOR_STR = 12
65
INTEGER, PARAMETER :: LIST_TYPE_ADDRINT = 13
66
67
INTEGER, PARAMETER :: SECTION_TYPE_BODY = 1
68
INTEGER, PARAMETER :: SECTION_TYPE_MATERIAL = 2
69
INTEGER, PARAMETER :: SECTION_TYPE_BF = 3
70
INTEGER, PARAMETER :: SECTION_TYPE_IC = 4
71
INTEGER, PARAMETER :: SECTION_TYPE_BC = 5
72
INTEGER, PARAMETER :: SECTION_TYPE_COMPONENT = 6
73
INTEGER, PARAMETER :: SECTION_TYPE_SIMULATION = 7
74
INTEGER, PARAMETER :: SECTION_TYPE_CONSTANTS = 8
75
INTEGER, PARAMETER :: SECTION_TYPE_EQUATION = 9
76
77
78
INTEGER, PARAMETER :: MAX_FNC = 32
79
80
interface ElmerEvalLua
81
module procedure ElmerEvalLuaS, ElmerEvalLuaT, ElmerEvalLuaV
82
end INTERFACE
83
84
TYPE String_stack_t
85
CHARACTER(:), ALLOCATABLE :: Name
86
TYPE(String_stack_t), POINTER :: Next => Null()
87
END TYPE String_stack_t
88
89
CHARACTER(:), ALLOCATABLE, SAVE, PRIVATE :: Namespace
90
!$OMP THREADPRIVATE(NameSpace)
91
92
TYPE(String_stack_t), SAVE, PRIVATE, POINTER :: Namespace_stack => Null()
93
!$OMP THREADPRIVATE(NameSpace_stack)
94
95
CHARACTER(:), ALLOCATABLE, SAVE, PRIVATE :: ActiveListName
96
!$OMP THREADPRIVATE(ActiveListName)
97
98
TYPE(String_stack_t), SAVE, PRIVATE, POINTER :: Activename_stack => Null()
99
!$OMP THREADPRIVATE(Activename_stack)
100
101
TYPE(ValueList_t), POINTER, SAVE, PRIVATE :: TimerList => NULL()
102
LOGICAL, SAVE, PRIVATE :: TimerPassive, TimerCumulative, TimerRealTime, TimerCPUTime
103
CHARACTER(LEN=MAX_NAME_LEN), SAVE, PRIVATE :: TimerPrefix
104
105
106
LOGICAL, PRIVATE :: DoNamespaceCheck = .FALSE.
107
108
CONTAINS
109
110
111
! MATC utilities to get scalar,vector & array results from given expression
112
! in input string variable.
113
!---------------------------------------------------------------------------
114
SUBROUTINE SetGetMatcParams(nparams,params,resul)
115
INTEGER :: nparams
116
REAL(KIND=dp) :: params(:)
117
CHARACTER(*), OPTIONAL :: resul
118
119
INTEGER :: i,j,l
120
CHARACTER(LEN=MAX_STRING_LEN) :: pcmd,res
121
122
IF(nparams==0) THEN
123
pcmd = "tx=0"
124
ELSE
125
#if 0
126
WRITE(pcmd,*) [(params(i),i=1,nparams)]
127
#else
128
! cray ftn output from above can be somewhat convoluted, do this instead
129
j = 1
130
DO i=1,nparams
131
WRITE(pcmd(j:), *) params(i)
132
DO WHILE(pcmd(j:j) == ' '); j=j+1; END DO
133
DO WHILE(pcmd(j:j) /= ' '); j=j+1; END DO
134
IF(pcmd(j-1:j-1)=='.') pcmd(j-1:j-1) = ' '
135
j = j + 1
136
END DO
137
#endif
138
IF(PRESENT(resul)) THEN
139
pcmd = TRIM(resul)//'='//TRIM(pcmd)
140
ELSE
141
pcmd = "tx="//TRIM(pcmd)
142
END IF
143
END IF
144
l = Matc(pcmd,res)
145
END SUBROUTINE SetGetMatcParams
146
147
148
FUNCTION GetMatcRealArray(cmd,n,m,nparams,params,resul) RESULT(g)
149
REAL(KIND=dp), ALLOCATABLE :: g(:,:)
150
CHARACTER(*) :: cmd
151
INTEGER :: n,m
152
INTEGER, OPTIONAL :: nparams
153
CHARACTER(*), OPTIONAL :: resul
154
REAL(KIND=dp), OPTIONAL :: params(:)
155
156
INTEGER :: i,j,l
157
CHARACTER(LEN=MAX_STRING_LEN) :: res
158
159
IF (PRESENT(nparams).AND.PRESENT(params))THEN
160
CALL SetGetMatcParams(nparams,params,resul)
161
END IF
162
l = Matc(cmd,res)
163
ALLOCATE(g(n,m))
164
READ(res(1:l),*) ((g(i,j),j=1,m),i=1,n)
165
END FUNCTION GetMatcRealArray
166
167
168
FUNCTION GetMatcRealVector(cmd,n,nparams,params,resul) RESULT(g)
169
REAL(KIND=dp), ALLOCATABLE :: g(:)
170
CHARACTER(*) :: cmd
171
INTEGER :: n,m
172
INTEGER, OPTIONAL :: nparams
173
CHARACTER(*), OPTIONAL :: resul
174
REAL(KIND=dp), OPTIONAL :: params(:)
175
176
INTEGER :: i,j,l
177
CHARACTER(LEN=MAX_NAME_LEN) :: res
178
179
IF (PRESENT(nparams).AND.PRESENT(params))THEN
180
CALL SetGetMatcParams(nparams,params,resul)
181
END IF
182
l = Matc(cmd,res)
183
ALLOCATE(g(n))
184
READ(res(1:l),*) (g(i),i=1,n)
185
END FUNCTION GetMatcRealVector
186
187
188
FUNCTION GetMatcReal(cmd,nparams,params,resul) RESULT(g)
189
CHARACTER(*) :: cmd
190
REAL(KIND=dp) :: g
191
INTEGER, OPTIONAL :: nparams
192
CHARACTER(*), OPTIONAL :: resul
193
REAL(KIND=dp), OPTIONAL :: params(:)
194
195
CHARACTER(LEN=MAX_STRING_LEN) :: pcmd, res
196
INTEGER :: i,l
197
198
IF (PRESENT(nparams).AND.PRESENT(params))THEN
199
CALL SetGetMatcParams(nparams,params,resul)
200
END IF
201
l = Matc(cmd,res)
202
READ(res(1:l), *) g
203
END FUNCTION GetMatcReal
204
!------------------------------------------------------------------------------
205
206
207
!> Tag the active degrees of freedom and number them in order of appearance.
208
!------------------------------------------------------------------------------
209
FUNCTION InitialPermutation( Perm,Model,Solver,Mesh, &
210
Equation,DGSolver,GlobalBubbles ) RESULT(k)
211
!------------------------------------------------------------------------------
212
USE PElementMaps
213
USE SParIterGlobals
214
TYPE(Model_t) :: Model
215
TYPE(Mesh_t) :: Mesh
216
TYPE(Solver_t), TARGET :: Solver
217
INTEGER :: Perm(:)
218
CHARACTER(LEN=*) :: Equation
219
LOGICAL, OPTIONAL :: DGSolver, GlobalBubbles
220
!------------------------------------------------------------------------------
221
INTEGER i,j,l,t,n,m,e,k,k1, MaxNDOFs, MaxEDOFs, MaxFDOFs, BDOFs, ndofs, el_id
222
INTEGER :: NodalIndexOffset, EdgeIndexOffset, FaceIndexOffset, Indexes(128)
223
INTEGER, POINTER :: Def_Dofs(:)
224
INTEGER, ALLOCATABLE :: EdgeDOFs(:), FaceDOFs(:)
225
LOGICAL :: FoundDG, DG, DB, GB, Bubbles, Found, Radiation, Parallel
226
TYPE(Element_t),POINTER :: Element, Edge, Face
227
CHARACTER(*), PARAMETER :: Caller = 'InitialPermutation'
228
!------------------------------------------------------------------------------
229
Perm = 0
230
k = 0
231
MaxEDOFs = Mesh % MaxEdgeDOFs
232
MaxFDOFs = Mesh % MaxFaceDOFs
233
MaxNDOFs = Mesh % MaxNDOFs
234
NodalIndexOffset = MaxNDOFs * Mesh % NumberOfNodes
235
EdgeIndexOffset = MaxEDOFs * Mesh % NumberOfEdges
236
FaceIndexOffset = MaxFDOFs * Mesh % NumberOfFaces
237
238
GB = .FALSE.
239
IF ( PRESENT(GlobalBubbles) ) GB=GlobalBubbles
240
241
DG = .FALSE.
242
IF ( PRESENT(DGSolver) ) DG=DGSolver
243
FoundDG = .FALSE.
244
245
IF( DG ) THEN
246
DB = ListGetLogical( Solver % Values,'DG Reduced Basis',Found )
247
ELSE
248
DB = .FALSE.
249
END IF
250
251
! Discontinuous bodies need special body-wise numbering
252
IF ( DB ) THEN
253
BLOCK
254
INTEGER, ALLOCATABLE :: NodeIndex(:)
255
INTEGER :: body_id, MaxGroup, group0, group
256
INTEGER, POINTER :: DgMap(:), DgMaster(:), DgSlave(:)
257
LOGICAL :: GotDgMap, GotMaster, GotSlave
258
!------------------------------------------------------------------------------
259
260
DgMap => ListGetIntegerArray( Solver % Values,'DG Reduced Basis Mapping',GotDgMap )
261
DgMaster => ListGetIntegerArray( Solver % Values,'DG Reduced Basis Master Bodies',GotMaster )
262
DgSlave => ListGetIntegerArray( Solver % Values,'DG Reduced Basis Slave Bodies',GotSlave )
263
264
IF( GotDgMap ) THEN
265
IF( SIZE( DgMap ) /= Model % NumberOfBodies ) THEN
266
CALL Fatal(Caller,'Invalid size of > Dg Reduced Basis Mapping <')
267
END IF
268
MaxGroup = MAXVAL( DgMap )
269
ELSE IF( GotMaster ) THEN
270
MaxGroup = 2
271
ELSE
272
MaxGroup = Model % NumberOfBodies
273
END IF
274
275
ALLOCATE( NodeIndex( Mesh % NumberOfNodes ) )
276
277
DO group0 = 1, MaxGroup
278
279
! If we have master-slave lists then nullify the slave nodes at the master
280
! interface since we want new indexes here.
281
IF( GotSlave .AND. group0 == 2 ) THEN
282
DO t=1,Mesh % NumberOfBulkElements
283
Element => Mesh % Elements(t)
284
group = Element % BodyId
285
IF( ANY( DgSlave == group ) ) THEN
286
NodeIndex( Element % NodeIndexes ) = 0
287
END IF
288
END DO
289
ELSE
290
! In generic case nullify all indexes already set
291
NodeIndex = 0
292
END IF
293
294
k1 = k
295
296
CALL Info(Caller,&
297
'Group '//I2S(group0)//' starts from index '//I2S(k1),Level=10)
298
299
DO t=1,Mesh % NumberOfBulkElements
300
Element => Mesh % Elements(t)
301
302
group = Element % BodyId
303
304
IF( GotMaster ) THEN
305
IF( group0 == 1 ) THEN
306
! First loop number dofs in "master bodies" only
307
IF( .NOT. ANY( DgMaster == group ) ) CYCLE
308
ELSE
309
! Second loop number dofs in all bodies except "master bodies"
310
IF( ANY( DgMaster == group ) ) CYCLE
311
END IF
312
ELSE IF( GotDgMap ) THEN
313
group = DgMap( group )
314
IF( group0 /= group ) CYCLE
315
ELSE
316
IF( group0 /= group ) CYCLE
317
END IF
318
319
IF ( CheckElementEquation(Model,Element,Equation) ) THEN
320
FoundDG = FoundDG .OR. Element % DGDOFs > 0
321
DO i=1,Element % DGDOFs
322
j = Element % NodeIndexes(i)
323
IF( NodeIndex(j) == 0 ) THEN
324
k = k + 1
325
NodeIndex(j) = k
326
END IF
327
Perm( Element % DGIndexes(i) ) = NodeIndex(j)
328
END DO
329
END IF
330
END DO
331
332
IF( k > k1 ) THEN
333
CALL Info( Caller,'Group '//I2S(group0)//&
334
' has '//I2S(k-k1)//' db dofs',Level=15)
335
END IF
336
END DO
337
338
CALL Info(Caller,'Numbered '//I2S(k)//&
339
' db nodes from bulk hits',Level=15)
340
341
IF ( FoundDG ) THEN
342
GOTO 10
343
! RETURN ! Discontinuous bodies !!!
344
END IF
345
END BLOCK
346
END IF
347
348
349
IF ( DG ) THEN
350
DO t=1,Mesh % NumberOfEdges
351
n = 0
352
Element => Mesh % Edges(t) % BoundaryInfo % Left
353
IF ( ASSOCIATED( Element ) ) THEN
354
IF ( CheckElementEquation(Model,Element,Equation) ) THEN
355
FoundDG = FoundDG .OR. Element % DGDOFs > 0
356
DO j=1,Element % DGDOFs
357
n = n + 1
358
Indexes(n) = Element % DGIndexes(j)
359
END DO
360
END IF
361
END IF
362
363
Element => Mesh % Edges(t) % BoundaryInfo % Right
364
IF ( ASSOCIATED( Element ) ) THEN
365
IF ( CheckElementEquation(Model,Element,Equation) ) THEN
366
FoundDG = FoundDG .OR. Element % DGDOFs > 0
367
DO j=1,Element % DGDOFs
368
n = n + 1
369
Indexes(n) = Element % DGIndexes(j)
370
END DO
371
END IF
372
END IF
373
374
DO i=1,n
375
j = Indexes(i)
376
IF ( Perm(j) == 0 ) THEN
377
k = k + 1
378
Perm(j) = k
379
END IF
380
END DO
381
END DO
382
383
CALL Info(Caller,'Numbered '//I2S(k)//&
384
' nodes from face hits',Level=15)
385
k1 = k
386
387
388
DO t=1,Mesh % NumberOfFaces
389
n = 0
390
Element => Mesh % Faces(t) % BoundaryInfo % Left
391
IF ( ASSOCIATED( Element ) ) THEN
392
IF ( CheckElementEquation(Model,Element,Equation) ) THEN
393
FoundDG = FoundDG .OR. Element % DGDOFs > 0
394
DO j=1,Element % DGDOFs
395
n = n + 1
396
Indexes(n) = Element % DGIndexes(j)
397
END DO
398
END IF
399
END IF
400
401
Element => Mesh % Faces(t) % BoundaryInfo % Right
402
IF ( ASSOCIATED( Element ) ) THEN
403
IF ( CheckElementEquation(Model,Element,Equation) ) THEN
404
FoundDG = FoundDG .OR. Element % DGDOFs > 0
405
DO j=1,Element % DGDOFs
406
n = n + 1
407
Indexes(n) = Element % DGIndexes(j)
408
END DO
409
END IF
410
END IF
411
412
DO i=1,n
413
j = Indexes(i)
414
IF ( Perm(j) == 0 ) THEN
415
k = k + 1
416
Perm(j) = k
417
END IF
418
END DO
419
END DO
420
421
CALL Info(Caller,'Numbered '//I2S(k-k1)//&
422
' nodes from bulk hits',Level=15)
423
424
IF ( FoundDG ) THEN
425
GOTO 10
426
! RETURN ! Discontinuous galerkin !!!
427
END IF
428
END IF
429
430
! In the case of p-elements two neighbouring elements may have different
431
! degrees of approximation, find out the highest order associated with
432
! a particular edge or face:
433
!
434
IF ( ANY(Solver % Def_Dofs(:,:,6)>=1) ) THEN
435
IF ( Mesh % NumberOFEdges>0 ) THEN
436
ALLOCATE(EdgeDOFs(Mesh % NumberOfEdges))
437
EdgeDOFs=0;
438
END IF
439
440
IF ( Mesh % NumberOFFaces>0 ) THEN
441
ALLOCATE(FaceDOFs(Mesh % NumberOfFaces))
442
FaceDOFs=0;
443
END IF
444
445
n = Mesh % NumberOfBulkElements + Mesh % NumberOFBoundaryElements
446
t = 1
447
DO WHILE( t <= n )
448
DO WHILE( t<=n )
449
Element => Mesh % Elements(t)
450
IF ( CheckElementEquation( Model, Element, Equation ) ) EXIT
451
t = t + 1
452
END DO
453
IF ( t>n ) EXIT
454
455
el_id = Element % TYPE % ElementCode / 100
456
457
Def_Dofs => Solver % Def_Dofs(el_id,Element % BodyId,:)
458
IF ( ASSOCIATED(Element % EdgeIndexes) ) THEN
459
IF(Element % Type % ElementCode >= 300) THEN
460
DO i=1,Element % TYPE % NumberOfEdges
461
j = Element % EdgeIndexes(i)
462
EdgeDOFs(j)=MAX(EdgeDOFs(j),getEdgeDOFs(Element,Def_Dofs(6)))
463
END DO
464
END IF
465
END IF
466
467
IF ( ASSOCIATED(Element % FaceIndexes) ) THEN
468
IF(Element % Type % ElementCode >= 500) THEN
469
DO i=1,Element % TYPE % NumberOfFaces
470
j = Element % FaceIndexes(i)
471
FaceDOFs(j)=MAX(FaceDOFs(j),getFaceDOFs(Element,Def_Dofs(6),i, &
472
Mesh % Faces(j)) )
473
END DO
474
END IF
475
END IF
476
t=t+1
477
END DO
478
END IF
479
480
481
n = Mesh % NumberOfBulkElements + Mesh % NumberOFBoundaryElements
482
t = 1
483
DO WHILE( t <= n )
484
485
DO WHILE( t<=n )
486
Element => Mesh % Elements(t)
487
IF ( CheckElementEquation( Model, Element, Equation ) ) EXIT
488
t = t + 1
489
END DO
490
491
IF ( t > n ) EXIT
492
493
el_id = Element % TYPE % ElementCode / 100
494
Def_Dofs => Solver % Def_Dofs(el_id,Element % BodyId,:)
495
496
ndofs = Def_Dofs(1)
497
IF (ndofs > 0) THEN
498
DO i=1,Element % TYPE % NumberOfNodes
499
DO j=1,ndofs
500
l = MaxNDOFs * (Element % NodeIndexes(i)-1) + j
501
IF ( Perm(l) == 0 ) THEN
502
k = k + 1
503
Perm(l) = k
504
END IF
505
END DO
506
END DO
507
END IF
508
509
IF ( ASSOCIATED( Element % EdgeIndexes ) ) THEN
510
DO i=1,Element % TYPE % NumberOfEdges
511
Edge => Mesh % Edges( Element % EdgeIndexes(i) )
512
IF(Element % Type % ElementCode==Edge % Type % ElementCode.AND..NOT.GB) CYCLE
513
514
ndofs = 0
515
IF ( Def_Dofs(2) >= 0) THEN
516
ndofs = Def_Dofs(2)
517
ELSE IF (Def_Dofs(6)>1) THEN
518
ndofs = EdgeDOFs(Element % EdgeIndexes(i))
519
END IF
520
521
DO e=1,ndofs
522
j = NodalIndexOffset + MaxEDOFs*(Element % EdgeIndexes(i)-1) + e
523
IF ( Perm(j) == 0 ) THEN
524
k = k + 1
525
Perm(j) = k
526
END IF
527
END DO
528
END DO
529
END IF
530
531
IF ( ASSOCIATED( Element % FaceIndexes ) ) THEN
532
DO i=1,Element % TYPE % NumberOfFaces
533
Face => Mesh % Faces( Element % FaceIndexes(i) )
534
IF(Element % Type % ElementCode==Face % Type % ElementCode.AND..NOT.GB) CYCLE
535
536
l = MAX(0,Def_Dofs(3))
537
j = Face % TYPE % ElementCode/100
538
539
IF(l==0) THEN
540
!
541
! NOTE: This depends on what dofs have been introduced
542
! by using the construct "-quad_face b: ..." and
543
! "-tri_face b: ..."
544
!
545
IF (ASSOCIATED(Face % BoundaryInfo % Left)) THEN
546
e = Face % BoundaryInfo % Left % BodyId
547
l = MAX(0,Solver % Def_Dofs(j+6,e,5))
548
END IF
549
IF (ASSOCIATED(Face % BoundaryInfo % Right)) THEN
550
e = Face % BoundaryInfo % Right % BodyId
551
l = MAX(l,Solver % Def_Dofs(j+6,e,5))
552
END IF
553
END IF
554
555
ndofs = 0
556
IF (l > 0) THEN
557
ndofs = l
558
ELSE IF (Def_Dofs(6)>1) THEN
559
ndofs = FaceDOFs(Element % FaceIndexes(i))
560
END IF
561
562
DO e=1,ndofs
563
j = NodalIndexOffset + EdgeIndexOffset + &
564
MaxFDOFs*(Element % FaceIndexes(i)-1) + e
565
IF ( Perm(j) == 0 ) THEN
566
k = k + 1
567
Perm(j) = k
568
END IF
569
END DO
570
END DO
571
END IF
572
573
IF ( GB .AND. ASSOCIATED(Element % BubbleIndexes) ) THEN
574
ndofs = 0
575
BDOFs = Def_Dofs(5)
576
j = Def_Dofs(6)
577
IF (BDOFs >= 0 .OR. j >= 1) THEN
578
! Apparently an "Element" command has been given so we use
579
! the given definition
580
IF (j > 1) ndofs = GetBubbleDOFs(Element, j)
581
ndofs = MAX(BDOFs, ndofs)
582
ELSE
583
! Apparently no "Element" command has been given which should
584
! activate the use of bubbles. Then the only way to activate the use of
585
! bubbles seems to be "Bubbles" command. If this is not present, we
586
! see no reason to add the indexes for bubble DOFs
587
Bubbles = ListGetLogical(Solver % Values, 'Bubbles', Found )
588
! The following is not a right way to obtain the bubble count
589
! in order to support solverwise definitions
590
IF (Bubbles) ndofs = SIZE(Element % BubbleIndexes)
591
END IF
592
593
DO i=1,ndofs
594
j = NodalIndexOffset + EdgeIndexOffset + &
595
FaceIndexOffset + Element % BubbleIndexes(i)
596
IF ( Perm(j) == 0 ) THEN
597
k = k + 1
598
Perm(j) = k
599
END IF
600
END DO
601
END IF
602
603
t = t + 1
604
END DO
605
606
Radiation = ListGetLogical( Solver % Values, 'Radiation Solver', Found )
607
IF ( Radiation ) THEN
608
Parallel = ParEnv % PEs>1
609
t = Mesh % NumberOfBulkElements + 1
610
n = Mesh % NumberOfBulkElements + Mesh % NumberOfBoundaryElements
611
DO WHILE( t<= n )
612
Element => Mesh % Elements(t)
613
IF ( RadiationCheck(Element) ) THEN
614
DO i=1,Element % TYPE % NumberOfNodes
615
j = Element % NodeIndexes(i)
616
IF ( Perm(j) == 0 ) THEN
617
k = k + 1
618
Perm(j) = k
619
END IF
620
END DO
621
END IF
622
t = t + 1
623
END DO
624
END IF
625
626
t = Mesh % NumberOfBulkElements + 1
627
n = Mesh % NumberOfBulkElements + Mesh % NumberOfBoundaryElements
628
DO WHILE( t<= n )
629
Element => Mesh % Elements(t)
630
IF ( Element % TYPE % ElementCode == 102 ) THEN
631
DO i=1,Element % TYPE % NumberOfNodes
632
j = Element % NodeIndexes(i)
633
IF ( Perm(j) == 0 ) THEN
634
k = k + 1
635
Perm(j) = k
636
END IF
637
END DO
638
END IF
639
t = t + 1
640
END DO
641
642
! Here we create the initial permutation such that the conforming dofs are eliminated.
643
IF( ListGetLogical( Solver % Values,'Apply Conforming BCs',Found ) ) THEN
644
BLOCK
645
INTEGER, POINTER :: TmpPerm(:)
646
LOGICAL, POINTER :: TmpFlip(:)
647
648
IF(.NOT. ASSOCIATED( Mesh % PeriodicPerm ) ) THEN
649
CALL Warn(Caller,'Conforming BC is requested but not generated!')
650
ELSE
651
Solver % PeriodicFlipActive = .FALSE.
652
n = SIZE( Mesh % PeriodicPerm )
653
m = SIZE( Perm )
654
655
IF( n < m ) THEN
656
CALL Info(Caller,'Increasing size of periodic tables from '&
657
//I2S(n)//' to '//I2S(SIZE(Perm))//'!',Level=7)
658
ALLOCATE( TmpPerm(SIZE(Perm)) )
659
TmpPerm = 0
660
TmpPerm(1:n) = Mesh % PeriodicPerm(1:n)
661
DEALLOCATE(Mesh % PeriodicPerm)
662
Mesh % PeriodicPerm => TmpPerm
663
664
IF(ASSOCIATED(Mesh % PeriodicFlip ) ) THEN
665
ALLOCATE( TmpFlip(SIZE(Perm)) )
666
TmpFlip = .FALSE.
667
TmpFlip(1:n) = Mesh % PeriodicFlip(1:n)
668
DEALLOCATE(Mesh % PeriodicFlip)
669
Mesh % PeriodicFlip => TmpFlip
670
END IF
671
END IF
672
673
n = 0
674
IF( ASSOCIATED( Mesh % PeriodicPerm ) ) THEN
675
! Set the eliminated dofs to zero and renumber
676
WHERE( Mesh % PeriodicPerm(1:m) > 0 ) Perm = -Perm
677
678
k = 0
679
DO i=1,m
680
IF( Perm(i) > 0 ) THEN
681
k = k + 1
682
Perm(i) = k
683
END IF
684
END DO
685
686
DO i=1,m
687
j = Mesh % PeriodicPerm(i)
688
IF( j > 0 ) THEN
689
IF( Perm(i) /= 0 ) THEN
690
Perm(i) = Perm(j)
691
IF(Mesh % PeriodicFlip(i)) n = n + 1
692
END IF
693
END IF
694
END DO
695
696
Solver % PeriodicFlipActive = ( n > 0 )
697
CALL Info(Caller,'Number of periodic flips in the field: '//I2S(n),Level=8)
698
END IF
699
END IF
700
END BLOCK
701
END IF
702
703
IF ( ALLOCATED(EdgeDOFs) ) DEALLOCATE(EdgeDOFs)
704
IF ( ALLOCATED(FaceDOFs) ) DEALLOCATE(FaceDOFs)
705
706
10 CONTINUE
707
708
!------------------------------------------------------------------------------
709
END FUNCTION InitialPermutation
710
!------------------------------------------------------------------------------
711
712
713
!---------------------------------------------------------------------------
714
FUNCTION RadiationCheck(Element) RESULT(L)
715
!---------------------------------------------------------------------------
716
LOGICAL :: L, Found
717
718
INTEGER :: t
719
720
TYPE(Element_t), POINTER :: Element
721
TYPE(ValueList_t), POINTER :: BC
722
CHARACTER(:), ALLOCATABLE :: RadiationFlag
723
724
L = .FALSE.
725
IF ( Element % Type % ElementCode<=1 ) RETURN
726
727
t = Element % BoundaryInfo % Constraint
728
IF(t<=0 .OR. t>SIZE(CurrentModel % BCs)) RETURN
729
730
BC => CurrentModel % BCs(t) % Values
731
RadiationFlag = ListGetString( BC, 'Radiation', Found )
732
IF (RadiationFlag=='diffuse gray' .OR. ListGetLogical(BC,'Radiator BC',Found)) L=.TRUE.
733
!---------------------------------------------------------------------------
734
END FUNCTION RadiationCheck
735
!---------------------------------------------------------------------------
736
737
738
!---------------------------------------------------------------------------
739
!> Check if given element belongs to a body for which given equation
740
!> should be solved.
741
!---------------------------------------------------------------------------
742
FUNCTION CheckElementEquation( Model,Element,Equation ) RESULT(Flag)
743
TYPE(Element_t), POINTER :: Element
744
TYPE(Model_t) :: Model
745
CHARACTER(LEN=*) :: Equation
746
CHARACTER(:), ALLOCATABLE :: PrevEquation
747
748
LOGICAL :: Flag,Found,PrevFlag
749
750
INTEGER :: k,body_id,prev_body_id = -1
751
752
SAVE Prev_body_id, PrevEquation, PrevFlag
753
!$OMP THREADPRIVATE(Prev_body_id, PrevEquation, PrevFlag)
754
755
body_id = Element % BodyId
756
757
IF( body_id == prev_body_id) THEN
758
IF (Equation == PrevEquation) THEN
759
Flag = PrevFlag
760
RETURN
761
END IF
762
END IF
763
764
prev_body_id = body_id
765
PrevEquation = Equation
766
767
Flag = .FALSE.
768
IF ( body_id > 0 .AND. body_id <= Model % NumberOfBodies ) THEN
769
k = ListGetInteger( Model % Bodies(body_id) % Values, 'Equation', Found, &
770
minv=1, maxv=Model % NumberOFEquations )
771
IF ( k > 0 ) THEN
772
Flag = ListGetLogical(Model % Equations(k) % Values,Equation,Found)
773
END IF
774
END IF
775
PrevFlag = Flag
776
777
!---------------------------------------------------------------------------
778
END FUNCTION CheckElementEquation
779
!---------------------------------------------------------------------------
780
781
782
!------------------------------------------------------------------------------
783
!> Changes the string to all lower case to allow string comparison.
784
!------------------------------------------------------------------------------
785
FUNCTION StringToLowerCase( to,from,same_len ) RESULT(n)
786
!------------------------------------------------------------------------------
787
CHARACTER(LEN=*), INTENT(in) :: from
788
CHARACTER(LEN=*), INTENT(out) :: to
789
LOGICAL, OPTIONAL, INTENT(in) :: same_len
790
!------------------------------------------------------------------------------
791
INTEGER :: n
792
INTEGER :: i,j,nlen
793
INTEGER, PARAMETER :: A=ICHAR('A'),Z=ICHAR('Z'),U2L=ICHAR('a')-ICHAR('A')
794
795
n = LEN(to)
796
IF (.NOT.PRESENT(same_len)) THEN
797
DO i=LEN(from),1,-1
798
IF ( from(i:i) /= ' ' ) EXIT
799
END DO
800
IF ( n>i ) THEN
801
to(i+1:n) = ' '
802
n=i
803
END IF
804
END IF
805
806
nlen = n
807
DO i=1,nlen
808
j = ICHAR( from(i:i) )
809
IF ( j >= A .AND. j <= Z ) THEN
810
to(i:i) = CHAR(j+U2L)
811
ELSE
812
to(i:i) = from(i:i)
813
IF ( to(i:i)=='[') n=i-1
814
END IF
815
END DO
816
END FUNCTION StringToLowerCase
817
!------------------------------------------------------------------------------
818
819
820
!------------------------------------------------------------------------------
821
!> Inserts totally legit variable to variable list.
822
!------------------------------------------------------------------------------
823
SUBROUTINE VariableAppend( Variables,NewVar)
824
!------------------------------------------------------------------------------
825
TYPE(Variable_t), POINTER :: Variables
826
TYPE(Variable_t), POINTER :: NewVar
827
!------------------------------------------------------------------------------
828
LOGICAL :: stat
829
TYPE(Variable_t), POINTER :: ptr,ptr1
830
LOGICAL :: Hit
831
INTEGER :: n,n1
832
CHARACTER(*), PARAMETER :: Caller = 'VariableAppend'
833
!------------------------------------------------------------------------------
834
835
836
CALL Info(Caller,'Inserting variable > '//TRIM(NewVar % Name)//&
837
' < of size '//I2S(SIZE(NewVar % Values)),Level=15)
838
839
IF ( .NOT.ASSOCIATED(NewVar) ) THEN
840
CALL Warn(Caller,'Cannot insert null variable to list!')
841
RETURN
842
END IF
843
844
IF ( .NOT.ASSOCIATED(Variables) ) THEN
845
CALL Warn(Caller,'Cannot insert variable to empty list!')
846
RETURN
847
END IF
848
849
n1 = LEN_TRIM( NewVar % Name )
850
851
852
Hit = .FALSE.
853
ptr => Variables
854
DO WHILE( ASSOCIATED( ptr ) )
855
n = LEN_TRIM( ptr % Name )
856
IF ( n == n1 ) THEN
857
IF ( ptr % Name(1:n) == NewVar % Name(1:n) ) THEN
858
Hit = .TRUE.
859
EXIT
860
END IF
861
END IF
862
ptr1 => ptr
863
ptr => ptr % Next
864
END DO
865
866
IF( Hit ) THEN
867
CALL Info(Caller,'Found variable in list: '//TRIM(NewVar % Name))
868
ELSE
869
CALL Info(Caller,'Append existing variable to end of list: '//TRIM(NewVar % Name))
870
ptr1 % Next => NewVar
871
NewVar % Next => NULL()
872
END IF
873
874
END SUBROUTINE VariableAppend
875
!------------------------------------------------------------------------------
876
877
878
879
!------------------------------------------------------------------------------
880
!> Adds a new variable to the list of variables.
881
!> The structures need to be allocated externally beforehand.
882
!------------------------------------------------------------------------------
883
SUBROUTINE VariableAdd( Variables,Mesh,Solver,Name,DOFs,Values,&
884
Perm,Output,Secondary,TYPE )
885
!------------------------------------------------------------------------------
886
TYPE(Variable_t), POINTER :: Variables
887
TYPE(Mesh_t), TARGET :: Mesh
888
TYPE(Solver_t), TARGET, OPTIONAL :: Solver
889
CHARACTER(LEN=*) :: Name
890
INTEGER :: DOFs
891
REAL(KIND=dp), POINTER :: Values(:)
892
INTEGER, OPTIONAL, POINTER :: Perm(:)
893
LOGICAL, OPTIONAL :: Output
894
LOGICAL, OPTIONAL :: Secondary
895
INTEGER, OPTIONAL :: TYPE
896
!------------------------------------------------------------------------------
897
LOGICAL :: stat
898
TYPE(Variable_t), POINTER :: ptr,ptr1,ptr2
899
TYPE(Solver_t), POINTER :: VSolver
900
!------------------------------------------------------------------------------
901
902
IF(ASSOCIATED(Values)) THEN
903
CALL Info('VariableAdd','Adding variable > '//TRIM(Name)//&
904
' < of size '//I2S(SIZE(Values)),Level=15)
905
ELSE
906
CALL Info('VariableAdd','Adding variable > '//TRIM(Name), Level=15)
907
END IF
908
909
NULLIFY(VSolver)
910
IF (PRESENT(Solver)) VSolver => Solver
911
912
IF ( .NOT.ASSOCIATED(Variables) ) THEN
913
ALLOCATE(Variables)
914
ptr => Variables
915
ELSE
916
ALLOCATE( ptr )
917
END IF
918
919
ALLOCATE(CHARACTER(LEN_TRIM(Name))::ptr % Name)
920
ptr % NameLen = StringToLowerCase( ptr % Name,Name )
921
922
IF ( .NOT. ASSOCIATED(ptr, Variables) ) THEN
923
ptr1 => Variables
924
ptr2 => Variables
925
DO WHILE( ASSOCIATED( ptr1 ) )
926
IF ( ptr % Name == ptr1 % Name ) THEN
927
DEALLOCATE( ptr )
928
RETURN
929
END IF
930
ptr2 => ptr1
931
ptr1 => ptr1 % Next
932
END DO
933
ptr2 % Next => ptr
934
END IF
935
ptr % Next => NULL()
936
937
ptr % DOFs = DOFs
938
IF ( PRESENT( Perm ) ) THEN
939
ptr % Perm => Perm
940
ELSE
941
ptr % Perm => NULL()
942
END IF
943
ptr % Norm = 0.0d0
944
ptr % PrevNorm = 0.0d0
945
ptr % Values => Values
946
NULLIFY( ptr % PrevValues )
947
NULLIFY( ptr % EigenValues, ptr % EigenVectors )
948
949
ptr % NonlinChange = 0.0_dp
950
ptr % SteadyChange = 0.0_dp
951
ptr % NonlinValues => NULL()
952
ptr % SteadyValues => NULL()
953
ptr % NonlinIter = 0
954
955
ptr % Solver => VSolver
956
ptr % PrimaryMesh => Mesh
957
958
ptr % Valid = .TRUE.
959
ptr % Output = .TRUE.
960
ptr % Secondary = .FALSE.
961
ptr % ValuesChanged = .TRUE.
962
963
! Converged information undefined = -1, not = 0, yes = 1
964
ptr % NonlinConverged = -1
965
ptr % SteadyConverged = -1
966
967
IF ( PRESENT( Secondary ) ) THEN
968
ptr % Secondary = Secondary
969
END IF
970
971
IF ( PRESENT( TYPE ) ) THEN
972
ptr % TYPE = TYPE
973
ELSE
974
IF(.NOT. PRESENT(Perm) .AND. ASSOCIATED(Values)) THEN
975
IF(SIZE(Values) == DOFs) ptr % Type = Variable_global
976
END IF
977
END IF
978
979
IF ( PRESENT( Output ) ) ptr % Output = Output
980
981
982
!------------------------------------------------------------------------------
983
END SUBROUTINE VariableAdd
984
!------------------------------------------------------------------------------
985
986
987
!------------------------------------------------------------------------------
988
SUBROUTINE ReleaseVariableList( VariableList )
989
!------------------------------------------------------------------------------
990
USE SpariterGlobals
991
TYPE(Variable_t), POINTER :: VariableList
992
!------------------------------------------------------------------------------
993
REAL(KIND=dp), POINTER :: Ptr(:)
994
LOGICAL :: GotValues
995
INTEGER :: i, n, m
996
TYPE(Variable_t), POINTER :: Var, Var1
997
!------------------------------------------------------------------------------
998
999
Var => VariableList
1000
DO WHILE( ASSOCIATED( Var ) )
1001
1002
! This is used to skip variables such as time, timestep, timestep size etc.
1003
IF (ASSOCIATED(Var % Values) ) THEN
1004
IF( SIZE( Var % Values ) == Var % DOFs ) THEN
1005
Var => Var % Next
1006
CYCLE
1007
END IF
1008
END IF
1009
1010
SELECT CASE( Var % Name )
1011
CASE( 'coordinate 1', 'coordinate 2', 'coordinate 3' )
1012
Var => Var % Next
1013
CYCLE
1014
END SELECT
1015
1016
IF( InfoActive(30) ) THEN
1017
CALL Info('ReleaseVariableList','Trying to release variable: '//TRIM(Var % Name))
1018
END IF
1019
1020
IF( Var % Secondary ) THEN
1021
Var => Var % Next
1022
CYCLE
1023
END IF
1024
1025
IF (Var % DOFs > 1) THEN
1026
Var => Var % Next
1027
CYCLE
1028
END IF
1029
!
1030
! Check that the variable is actually allocated,
1031
! not pointer to some other variables memory:
1032
! ----------------------------------------------
1033
1034
GotValues = .TRUE.
1035
Var1 => VariableList
1036
DO WHILE( ASSOCIATED( Var1 ) )
1037
IF (.NOT.ASSOCIATED(Var,Var1)) THEN
1038
IF ( ASSOCIATED(Var1 % Values) ) THEN
1039
DO i=1,Var1 % DOFs
1040
ptr => Var1 % Values(i::Var1 % DOFs)
1041
IF ( ASSOCIATED(Var % Values,ptr) ) THEN
1042
GotValues = .FALSE.
1043
EXIT
1044
END IF
1045
END DO
1046
END IF
1047
END IF
1048
IF (.NOT. GotValues) EXIT
1049
Var1 => Var1 % Next
1050
END DO
1051
1052
IF (ASSOCIATED(Var % Values)) THEN
1053
IF(SIZE(Var % Values)<=0) GotValues = .FALSE.
1054
END IF
1055
1056
IF (ASSOCIATED(Var % Perm)) THEN
1057
Var1 => VariableList
1058
DO WHILE(ASSOCIATED(Var1))
1059
IF (.NOT.ASSOCIATED(Var,Var1)) THEN
1060
IF (ASSOCIATED(Var % Perm,Var1 % Perm)) &
1061
Var1 % Perm => NULL()
1062
END IF
1063
Var1 => Var1 % Next
1064
END DO
1065
1066
IF(SIZE(Var % Perm)>0) THEN
1067
DEALLOCATE( Var % Perm)
1068
ELSE
1069
GotValues = .FALSE.
1070
END IF
1071
END IF
1072
1073
IF ( GotValues ) THEN
1074
CALL DeallocateVariableEntries()
1075
END IF
1076
NULLIFY( Var % EigenVectors, Var % EigenValues )
1077
NULLIFY( Var % Values, Var % PrevValues, Var % Perm )
1078
NULLIFY( Var % SteadyValues, Var % NonlinValues )
1079
1080
Var => Var % Next
1081
END DO
1082
1083
Var => VariableList
1084
DO WHILE( ASSOCIATED( Var ) )
1085
IF ( Var % Secondary ) THEN
1086
Var => Var % Next
1087
CYCLE
1088
END IF
1089
1090
IF ( ASSOCIATED( Var % Perm ) ) THEN
1091
Var1 => VariableList
1092
DO WHILE(ASSOCIATED(Var1))
1093
IF (.NOT.ASSOCIATED(Var,Var1)) THEN
1094
IF (ASSOCIATED(Var % Perm,Var1 % Perm)) THEN
1095
Var1 % Perm => NULL()
1096
END IF
1097
END IF
1098
Var1 => Var1 % Next
1099
END DO
1100
IF (SIZE(Var % Perm)>0) THEN
1101
DEALLOCATE( Var % Perm )
1102
END IF
1103
END IF
1104
1105
IF ( Var % DOFs > 1 ) THEN
1106
CALL DeallocateVariableEntries()
1107
END IF
1108
1109
NULLIFY( Var % EigenVectors, Var % EigenValues )
1110
NULLIFY( Var % Values, Var % PrevValues, Var % Perm )
1111
NULLIFY( Var % SteadyValues, Var % NonlinValues )
1112
1113
Var => Var % Next
1114
END DO
1115
1116
1117
! Deallocate mesh variable list:
1118
! ------------------------------
1119
Var => VariableList
1120
DO WHILE( ASSOCIATED( Var ) )
1121
Var1 => Var % Next
1122
DEALLOCATE( Var )
1123
Var => Var1
1124
END DO
1125
1126
CONTAINS
1127
1128
SUBROUTINE DeallocateVariableEntries()
1129
1130
IF ( ASSOCIATED( Var % Values ) ) &
1131
DEALLOCATE( Var % Values )
1132
1133
IF ( ASSOCIATED( Var % PrevValues ) ) &
1134
DEALLOCATE( Var % PrevValues )
1135
1136
IF ( ASSOCIATED( Var % EigenValues ) ) &
1137
DEALLOCATE( Var % EigenValues )
1138
1139
IF ( ASSOCIATED( Var % EigenVectors ) ) &
1140
DEALLOCATE( Var % EigenVectors )
1141
1142
IF ( ASSOCIATED( Var % SteadyValues ) ) &
1143
DEALLOCATE( Var % SteadyValues )
1144
1145
IF ( ASSOCIATED( Var % NonlinValues ) ) &
1146
DEALLOCATE( Var % NonlinValues )
1147
1148
IF( ASSOCIATED( Var % ConstraintModesIndeces ) ) &
1149
DEALLOCATE( Var % ConstraintModesIndeces )
1150
1151
IF( ASSOCIATED( Var % ConstraintModes ) ) &
1152
DEALLOCATE( Var % ConstraintModes )
1153
1154
IF( ASSOCIATED( Var % UpperLimitActive ) ) &
1155
DEALLOCATE( Var % UpperLimitActive )
1156
1157
IF( ASSOCIATED( Var % LowerLimitActive ) ) &
1158
DEALLOCATE( Var % LowerLimitActive )
1159
1160
IF( ASSOCIATED( Var % IpTable ) ) &
1161
DEALLOCATE( Var % IpTable )
1162
1163
IF( ASSOCIATED( Var % CValues ) ) &
1164
DEALLOCATE( Var % CValues )
1165
1166
IF( ASSOCIATED( Var % PValues ) ) &
1167
DEALLOCATE( Var % PValues )
1168
1169
END SUBROUTINE DeallocateVariableEntries
1170
1171
!------------------------------------------------------------------------------
1172
END SUBROUTINE ReleaseVariableList
1173
!------------------------------------------------------------------------------
1174
1175
1176
!------------------------------------------------------------------------------
1177
!> Deletes a variable (by name) from list of variables
1178
!------------------------------------------------------------------------------
1179
SUBROUTINE VariableRemove(Variables, NameIn, WarnMiss)
1180
1181
IMPLICIT NONE
1182
!-----------------------------------------------
1183
TYPE(Variable_t), POINTER :: Variables
1184
CHARACTER(LEN=*) :: NameIn
1185
LOGICAL, OPTIONAL :: WarnMiss
1186
!-----------------------------------------------
1187
TYPE(Variable_t), POINTER :: Var, Prev, RmVar
1188
CHARACTER(LEN=LEN_TRIM(NameIn)) :: Name
1189
LOGICAL :: GotIt, WarnMissing
1190
INTEGER :: k
1191
1192
GotIt = .FALSE.
1193
IF(PRESENT(WarnMiss)) THEN
1194
WarnMissing = WarnMiss
1195
ELSE
1196
WarnMissing = .TRUE.
1197
END IF
1198
1199
Var => Variables
1200
Prev => NULL()
1201
k = StringToLowerCase(Name, NameIn,.TRUE.)
1202
1203
WRITE(Message,'(a,a)') "Removing variable: ",Name(1:k)
1204
CALL Info("VariableRemove",Message, Level=10)
1205
1206
!Find variable by name, and hook up % Next appropriately
1207
DO WHILE(ASSOCIATED(Var))
1208
IF( Var % NameLen == k ) THEN
1209
IF(Var % Name(1:k) == Name(1:k)) THEN
1210
GotIt = .TRUE.
1211
RmVar => Var
1212
IF(ASSOCIATED(Prev)) THEN
1213
!Link up variables either side of removed var
1214
Prev % Next => Var % Next
1215
ELSE
1216
!If this was the first variable, we point Variables
1217
!at the next one...
1218
Variables => Var % Next
1219
END IF
1220
EXIT
1221
END IF
1222
END IF
1223
Prev => Var
1224
Var => Prev % Next
1225
END DO
1226
1227
IF(.NOT. GotIt) THEN
1228
IF(WarnMissing) CALL Warn("VariableRemove","Couldn't find the variable, returning...")
1229
RETURN
1230
END IF
1231
1232
RmVar % Next => NULL()
1233
1234
!cycle other variables to check for Perm association
1235
IF (ASSOCIATED(RmVar % Perm)) THEN
1236
Var => Variables
1237
DO WHILE(ASSOCIATED(Var))
1238
IF(ASSOCIATED(RmVar, Var)) &
1239
CALL Fatal("VariableRemove", "Programming Error - Variable appears twice in list?")
1240
IF (ASSOCIATED(Var % Perm,RmVar % Perm)) THEN
1241
RmVar % Perm => NULL()
1242
EXIT
1243
END IF
1244
Var => Var % Next
1245
END DO
1246
1247
!ASSOCIATION between zero-length arrays cannot be tested
1248
!so nullify it anyway, just to be safe. Technically results
1249
!in a memory leak (of size zero??)
1250
IF(SIZE(RmVar % Perm) == 0) RmVar % Perm => NULL()
1251
END IF
1252
1253
1254
1255
!ReleaseVariableList was intended to deallocate an entire list of variables,
1256
!but by nullifying RmVar % Next, we have effectively isolated RmVar in
1257
!its own variable list.
1258
CALL ReleaseVariableList( RmVar )
1259
!------------------------------------------------------------------------------
1260
END SUBROUTINE VariableRemove
1261
!------------------------------------------------------------------------------
1262
1263
1264
1265
!------------------------------------------------------------------------------
1266
!> For vectors the individual components are added also to the list
1267
!> of variables. This routine makes the addition of vectors less laborious.
1268
!> Also allocates the field values if not given in the parameter list.
1269
!------------------------------------------------------------------------------
1270
SUBROUTINE VariableAddVector( Variables,Mesh,Solver,Name,DOFs,Values,&
1271
Perm,Output,Secondary,VarType,Global,InitValue,IpPoints,varsuffix)
1272
!------------------------------------------------------------------------------
1273
TYPE(Variable_t), POINTER :: Variables
1274
TYPE(Mesh_t), TARGET :: Mesh
1275
TYPE(Solver_t), TARGET, OPTIONAL :: Solver
1276
CHARACTER(LEN=*) :: Name
1277
INTEGER, OPTIONAL :: DOFs
1278
REAL(KIND=dp), OPTIONAL, POINTER :: Values(:)
1279
LOGICAL, OPTIONAL :: Output
1280
INTEGER, OPTIONAL, POINTER :: Perm(:)
1281
LOGICAL, OPTIONAL :: Secondary
1282
INTEGER, OPTIONAL :: VarType
1283
LOGICAL, OPTIONAL :: Global
1284
REAL(KIND=dp), OPTIONAL :: InitValue
1285
LOGICAL, OPTIONAL :: IpPoints
1286
CHARACTER(LEN=*), OPTIONAL :: VarSuffix
1287
!------------------------------------------------------------------------------
1288
CHARACTER(:), ALLOCATABLE :: tmpname
1289
REAL(KIND=dp), POINTER :: Component(:), TmpValues(:)
1290
INTEGER :: i,nsize, ndofs, FieldType
1291
LOGICAL :: IsPerm, IsGlobal, IsIPPoints
1292
!------------------------------------------------------------------------------
1293
1294
IF( PRESENT( DOFs ) ) THEN
1295
ndofs = Dofs
1296
ELSE
1297
ndofs = 1
1298
END IF
1299
1300
IsPerm = .FALSE.
1301
IsGlobal = .FALSE.
1302
IsIPPoints = .FALSE.
1303
1304
IsPerm = PRESENT( Perm )
1305
IF( PRESENT( Global ) ) IsGlobal = Global
1306
IF( PRESENT( IPPoints ) ) IsIPPoints = IPPoints
1307
1308
IF( PRESENT( VarType ) ) THEN
1309
FieldType = VarType
1310
ELSE
1311
FieldType = variable_on_nodes
1312
END IF
1313
1314
1315
1316
CALL Info('VariableAddVector','Adding variable > '//TRIM(Name)//' < with '&
1317
//I2S(ndofs)//' components',Level=15)
1318
1319
IF(PRESENT(Values)) THEN
1320
TmpValues => Values
1321
ELSE
1322
IF( IsPerm ) THEN
1323
nsize = MAXVAL( Perm )
1324
ELSE IF( IsGlobal ) THEN
1325
nsize = 1
1326
ELSE IF( IsIpPoints ) THEN
1327
IF( .NOT. PRESENT( Solver ) ) THEN
1328
CALL Fatal('VariableAddVector','Integration point variable needs a Solver!')
1329
END IF
1330
IF( .NOT. ASSOCIATED( Solver % IPTable ) ) THEN
1331
CALL Fatal('VariableAddVector','Integration point variable needs an IpTable')
1332
END IF
1333
nsize = Solver % IPTable % IPCount
1334
ELSE
1335
nsize = Mesh % NumberOfNodes
1336
END IF
1337
CALL Info('VariableAddVector','Allocating field of size: '//I2S(nsize),Level=12)
1338
1339
NULLIFY(TmpValues)
1340
ALLOCATE(TmpValues(ndofs*nsize))
1341
IF(.NOT. PRESENT(InitValue) ) THEN
1342
TmpValues = 0.0_dp
1343
END IF
1344
END IF
1345
1346
IF( PRESENT( InitValue ) ) THEN
1347
TmpValues = InitValue
1348
END IF
1349
1350
IF( nDOFs > 1 ) THEN
1351
DO i=1,nDOFs
1352
tmpname = ComponentName(Name,i)
1353
IF(PRESENT(VarSuffix)) tmpname = TRIM(tmpname)//' '//TRIM(VarSuffix)
1354
Component => TmpValues(i::nDOFs)
1355
CALL VariableAdd( Variables,Mesh,Solver,TmpName,1,Component,&
1356
Perm,Output,.TRUE.,VarType)
1357
END DO
1358
END IF
1359
1360
tmpname = TRIM(Name)
1361
IF(PRESENT(VarSuffix)) THEN
1362
tmpname = TRIM(tmpname)//' '//TRIM(VarSuffix)
1363
END IF
1364
1365
CALL VariableAdd( Variables,Mesh,Solver,tmpname,nDOFs,TmpValues,&
1366
Perm,Output,Secondary,VarType)
1367
1368
!------------------------------------------------------------------------------
1369
END SUBROUTINE VariableAddVector
1370
!------------------------------------------------------------------------------
1371
1372
1373
!------------------------------------------------------------------------------
1374
FUNCTION MeshProjector( Mesh1, Mesh2, &
1375
UseQuadrantTree, Trans ) RESULT( ProjectorMatrix )
1376
!------------------------------------------------------------------------------
1377
TYPE(Mesh_t) :: Mesh1, Mesh2
1378
LOGICAL, OPTIONAL :: UseQuadrantTree,Trans
1379
TYPE(Matrix_t), POINTER :: ProjectorMatrix
1380
!------------------------------------------------------------------------------
1381
TYPE(Projector_t), POINTER :: Projector
1382
!------------------------------------------------------------------------------
1383
INTERFACE
1384
SUBROUTINE InterpolateMeshToMeshQ( OldMesh, NewMesh, OldVariables, NewVariables, &
1385
UseQuadrantTree, Projector, MaskName, FoundNodes, NewMaskPerm, KeepUnfoundNodes )
1386
USE Types
1387
TYPE(Variable_t), POINTER, OPTIONAL :: OldVariables, NewVariables
1388
TYPE(Mesh_t), TARGET :: OldMesh, NewMesh
1389
LOGICAL, OPTIONAL :: UseQuadrantTree,FoundNodes(:)
1390
CHARACTER(LEN=*),OPTIONAL :: MaskName
1391
TYPE(Projector_t), POINTER, OPTIONAL :: Projector
1392
INTEGER, OPTIONAL, POINTER :: NewMaskPerm(:)
1393
LOGICAL, OPTIONAL :: KeepUnfoundNodes
1394
END SUBROUTINE InterpolateMeshToMeshQ
1395
END INTERFACE
1396
1397
IF ( PRESENT(UseQuadrantTree) ) THEN
1398
CALL InterpolateMeshToMeshQ( Mesh1, Mesh2, &
1399
UseQuadrantTree=UseQuadrantTree, Projector=Projector )
1400
ELSE
1401
CALL InterpolateMeshToMeshQ( Mesh1, Mesh2, Projector=Projector )
1402
END IF
1403
1404
ProjectorMatrix => Projector % Matrix
1405
IF ( PRESENT(Trans) ) THEN
1406
IF ( Trans ) THEN
1407
ProjectorMatrix => Projector % TMatrix
1408
END IF
1409
END IF
1410
!------------------------------------------------------------------------------
1411
END FUNCTION MeshProjector
1412
!------------------------------------------------------------------------------
1413
1414
1415
!------------------------------------------------------------------------------
1416
!> Find a variable by its name from the list of variables.
1417
!> If it is not found in the current mesh, interpolation between
1418
!> meshes is automatically requested for.
1419
!------------------------------------------------------------------------------
1420
RECURSIVE FUNCTION VariableGet( Variables, Name, ThisOnly, MaskName, UnfoundFatal, &
1421
DoInterp ) RESULT(Var)
1422
!------------------------------------------------------------------------------
1423
TYPE(Variable_t), POINTER :: Variables
1424
CHARACTER(LEN=*) :: Name
1425
LOGICAL, OPTIONAL :: ThisOnly
1426
CHARACTER(LEN=*),OPTIONAL :: MaskName
1427
LOGICAL, OPTIONAL :: UnfoundFatal, DoInterp
1428
!------------------------------------------------------------------------------
1429
TYPE(Mesh_t), POINTER :: Mesh
1430
TYPE(Projector_t), POINTER :: Projector
1431
TYPE(Variable_t), POINTER :: Var,PVar,Tmp,AidVar
1432
REAL(KIND=dp), POINTER :: Vals(:)
1433
INTEGER :: i,k,n, DOFs, MAXNDOFs
1434
LOGICAL :: Found, GlobalBubbles, UseProjector, HackMesh, ExecInterpolation
1435
CHARACTER(LEN=LEN_TRIM(Name)) :: str
1436
DOUBLE PRECISION :: t1
1437
CHARACTER(:), ALLOCATABLE :: tmpname
1438
!------------------------------------------------------------------------------
1439
INTERFACE
1440
SUBROUTINE InterpolateMeshToMesh( OldMesh, NewMesh, OldVariables, &
1441
NewVariables, UseQuadrantTree, Projector, MaskName, UnfoundNodes )
1442
USE Types
1443
TYPE(Variable_t), POINTER, OPTIONAL :: OldVariables, NewVariables
1444
TYPE(Mesh_t), TARGET :: OldMesh, NewMesh
1445
LOGICAL, OPTIONAL :: UseQuadrantTree
1446
LOGICAL, POINTER, OPTIONAL :: UnfoundNodes(:)
1447
CHARACTER(LEN=*),OPTIONAL :: MaskName
1448
TYPE(Projector_t), POINTER, OPTIONAL :: Projector
1449
END SUBROUTINE InterpolateMeshToMesh
1450
END INTERFACE
1451
!------------------------------------------------------------------------------
1452
1453
1454
ExecInterpolation = .TRUE.
1455
IF(PRESENT(DoInterp)) ExecInterpolation = DoInterp
1456
1457
k = StringToLowerCase( str,Name,.TRUE. )
1458
1459
Tmp => Variables
1460
DO WHILE( ASSOCIATED(tmp) )
1461
IF ( tmp % NameLen == k ) THEN
1462
IF ( tmp % Name(1:k) == str(1:k) ) THEN
1463
IF ( Tmp % Valid ) THEN
1464
Var => Tmp
1465
RETURN
1466
END IF
1467
EXIT
1468
END IF
1469
END IF
1470
tmp => tmp % Next
1471
END DO
1472
Var => Tmp
1473
1474
!------------------------------------------------------------------------------
1475
IF ( PRESENT(ThisOnly) ) THEN
1476
IF ( ThisOnly ) THEN
1477
IF ( PRESENT(UnfoundFatal) ) THEN
1478
IF ( UnfoundFatal ) THEN
1479
CALL Fatal("VariableGet","Failed to find variable "//TRIM(Name))
1480
END IF
1481
END IF
1482
RETURN
1483
END IF
1484
END IF
1485
1486
!------------------------------------------------------------------------------
1487
NULLIFY( PVar )
1488
Mesh => CurrentModel % Meshes
1489
DO WHILE( ASSOCIATED( Mesh ) )
1490
IF ( .NOT.ASSOCIATED( Variables, Mesh % Variables ) ) THEN
1491
PVar => VariableGet( Mesh % Variables, Name, ThisOnly=.TRUE. )
1492
IF ( ASSOCIATED( PVar ) ) THEN
1493
IF ( ASSOCIATED( Mesh, PVar % PrimaryMesh ) ) THEN
1494
EXIT
1495
END IF
1496
END IF
1497
END IF
1498
Mesh => Mesh % Next
1499
END DO
1500
1501
IF (.NOT.ASSOCIATED( PVar ) ) THEN
1502
IF ( PRESENT(UnfoundFatal) ) THEN
1503
IF ( UnfoundFatal ) THEN
1504
CALL Fatal("VariableGet","Failed to find or interpolate variable: "//TRIM(Name))
1505
END IF
1506
END IF
1507
RETURN
1508
END IF
1509
1510
! If the variable is of type "global" do not do all the stupid hassle to interpolate it.
1511
IF( pVar % TYPE == Variable_global ) THEN
1512
IF(.NOT. ASSOCIATED(Var)) THEN
1513
ALLOCATE(Var)
1514
END IF
1515
IF(.NOT. ASSOCIATED(Var % Values)) THEN
1516
ALLOCATE(Var % Values(SIZE(pVar % Values)))
1517
Var % Values = pVar % Values
1518
CALL VariableAdd( Variables, PVar % PrimaryMesh, PVar % Solver, &
1519
PVar % Name, PVar % DOFs, Var % Values, &
1520
Output = PVar % Output, TYPE = pVar % TYPE )
1521
Var => VariableGet( Variables, Name, ThisOnly=.TRUE. )
1522
END IF
1523
Var % Values = pVar % Values
1524
RETURN
1525
END IF
1526
1527
!------------------------------------------------------------------------------
1528
IF ( .NOT.ASSOCIATED( Tmp ) ) THEN
1529
GlobalBubbles = .FALSE.
1530
IF(ASSOCIATED(Pvar % Solver)) GlobalBubbles = Pvar % Solver % GlobalBubbles
1531
1532
Mesh => CurrentModel % Mesh
1533
IF (PVar % PrimaryMesh % MaxNDOFs /= Mesh % MaxNDOFs) THEN
1534
MaxNDOFs = Mesh % MaxNDOFs
1535
IF (PVar % PrimaryMesh % MaxNDOFs == 1) THEN
1536
! Try to tamper the mesh temporarily, so that the permutation will be created as if
1537
! one nodal field was present
1538
HackMesh = .TRUE.
1539
Mesh % MaxNDOFs = 1
1540
ELSE
1541
CALL Fatal('VariableGet', 'non-matching permutation occurs due to an element definition n:'//I2S(MaxNDOFs))
1542
END IF
1543
ELSE
1544
HackMesh = .FALSE.
1545
END IF
1546
1547
1548
DOFs = Mesh % NumberOfNodes
1549
DOFs = DOFs + Mesh % NumberOfEdges * Mesh % MaxEdgeDOFs
1550
DOFs = DOFs + Mesh % NumberOfFaces * Mesh % MaxFaceDOFs
1551
IF ( GlobalBubbles ) THEN
1552
DOFs = DOFs + CurrentModel % Mesh % MaxBDOFs * &
1553
CurrentModel % Mesh % NumberOfBulkElements
1554
END IF
1555
1556
ALLOCATE( Var )
1557
ALLOCATE( Var % Values(DOFs*Pvar % DOFs) )
1558
Var % Values = 0
1559
1560
NULLIFY( Var % Perm )
1561
IF (ASSOCIATED(PVar % Perm)) THEN
1562
ALLOCATE( Var % Perm(DOFs) )
1563
1564
n = InitialPermutation( Var % Perm, CurrentModel, PVar % Solver, &
1565
CurrentModel % Mesh, ListGetString(PVar % Solver % Values,'Equation'), &
1566
GlobalBubbles=GlobalBubbles )
1567
1568
IF ( n==0 ) n=CurrentModel % Mesh % NumberOfNodes
1569
IF ( n == CurrentModel % Mesh % NumberOfNodes ) THEN
1570
DO i=1,n
1571
Var % Perm(i) = i
1572
END DO
1573
END IF
1574
END IF
1575
1576
IF (HackMesh) CurrentModel % Mesh % MaxNDOFs = MaxNDOFs
1577
1578
CALL VariableAdd( Variables, PVar % PrimaryMesh, PVar % Solver, &
1579
PVar % Name, PVar % DOFs, Var % Values, Var % Perm, PVar % Output )
1580
1581
Var => VariableGet( Variables, Name, ThisOnly=.TRUE. )
1582
1583
NULLIFY( Var % PrevValues )
1584
IF ( ASSOCIATED( PVar % PrevValues ) ) THEN
1585
ALLOCATE( Var % PrevValues( DOFs, SIZE(PVar % PrevValues,2) ) )
1586
Var % PrevValues = 0._dp
1587
END IF
1588
1589
IF ( PVar % Name(1:PVar % NameLen) == 'flow solution' ) THEN
1590
Vals => Var % Values( 1: SIZE(Var % Values) : PVar % DOFs )
1591
CALL VariableAdd( Variables, PVar % PrimaryMesh, PVar % Solver, &
1592
'Velocity 1', 1, Vals, Var % Perm, PVar % Output )
1593
1594
Tmp => VariableGet( Variables, 'Velocity 1', .TRUE. )
1595
NULLIFY( Tmp % PrevValues )
1596
IF ( ASSOCIATED( Var % PrevValues ) ) &
1597
Tmp % PrevValues => Var % PrevValues(1::PVar % DOFs,:)
1598
1599
Vals => Var % Values( 2: SIZE(Var % Values) : PVar % DOFs )
1600
CALL VariableAdd( Variables, PVar % PrimaryMesh, PVar % Solver, &
1601
'Velocity 2', 1, Vals, Var % Perm, PVar % Output )
1602
1603
Tmp => VariableGet( Variables, 'Velocity 2', .TRUE. )
1604
NULLIFY( Tmp % PrevValues )
1605
IF ( ASSOCIATED( Var % PrevValues ) ) &
1606
Tmp % PrevValues => Var % PrevValues(2::PVar % DOFs,:)
1607
1608
IF ( PVar % DOFs == 3 ) THEN
1609
Vals => Var % Values( 3 : SIZE(Var % Values) : PVar % DOFs )
1610
CALL VariableAdd( Variables, PVar % PrimaryMesh, PVar % Solver, &
1611
'Pressure', 1, Vals, Var % Perm, PVar % Output )
1612
ELSE
1613
Vals => Var % Values( 3: SIZE(Var % Values) : PVar % DOFs )
1614
CALL VariableAdd( Variables, PVar % PrimaryMesh, PVar % Solver, &
1615
'Velocity 3', 1, Vals, Var % Perm, PVar % Output )
1616
1617
Tmp => VariableGet( Variables, 'Velocity 3', .TRUE. )
1618
NULLIFY( Tmp % PrevValues )
1619
IF ( ASSOCIATED( Var % PrevValues ) ) &
1620
Tmp % PrevValues => Var % PrevValues(3::PVar % DOFs,:)
1621
1622
Vals => Var % Values( 4: SIZE(Var % Values) : PVar % DOFs )
1623
CALL VariableAdd( Variables, PVar % PrimaryMesh, PVar % Solver, &
1624
'Pressure', 1, Vals, Var % Perm, PVar % Output )
1625
END IF
1626
1627
Tmp => VariableGet( Variables, 'Pressure', .TRUE. )
1628
NULLIFY( Tmp % PrevValues )
1629
IF ( ASSOCIATED( Var % PrevValues ) ) &
1630
Tmp % PrevValues => Var % PrevValues(PVar % DOFs::PVar % DOFs,:)
1631
ELSE
1632
IF ( PVar % DOFs > 1 ) THEN
1633
DO i=1,PVar % DOFs
1634
Vals => Var % Values( i: SIZE(Var % Values) : PVar % DOFs )
1635
tmpname = ComponentName( PVar % Name, i )
1636
CALL VariableAdd( Variables, PVar % PrimaryMesh, PVar % Solver, &
1637
tmpname, 1, Vals, Var % Perm, PVar % Output )
1638
1639
Tmp => VariableGet( Variables, tmpname, .TRUE. )
1640
NULLIFY( Tmp % PrevValues )
1641
IF ( ASSOCIATED( Var % PrevValues ) ) &
1642
Tmp % PrevValues => Var % PrevValues(i::PVar % DOFs,:)
1643
END DO
1644
END IF
1645
END IF
1646
1647
Var => VariableGet( Variables, Name, ThisOnly=.TRUE. )
1648
END IF
1649
1650
IF(.NOT.ExecInterpolation) RETURN
1651
!------------------------------------------------------------------------------
1652
! Build a temporary variable list of variables to be interpolated
1653
!------------------------------------------------------------------------------
1654
ALLOCATE( Tmp )
1655
Tmp = PVar
1656
Var => Tmp
1657
NULLIFY( Var % Next )
1658
1659
IF ( PVar % Name(1:PVar % NameLen) == 'flow solution' ) THEN
1660
ALLOCATE( Var % Next )
1661
Var => Var % Next
1662
Var = VariableGet( PVar % PrimaryMesh % Variables, 'Velocity 1' )
1663
1664
ALLOCATE( Var % Next )
1665
Var => Var % Next
1666
Var = VariableGet( PVar % PrimaryMesh % Variables, 'Velocity 2' )
1667
1668
IF ( PVar % DOFs == 4 ) THEN
1669
ALLOCATE( Var % Next )
1670
Var => Var % Next
1671
Var = VariableGet( PVar % PrimaryMesh % Variables, 'Velocity 3' )
1672
END IF
1673
1674
ALLOCATE( Var % Next )
1675
Var => Var % Next
1676
Var = VariableGet( PVar % PrimaryMesh % Variables, 'Pressure' )
1677
NULLIFY( Var % Next )
1678
Var => Tmp
1679
ELSE IF ( PVar % DOFs > 1 ) THEN
1680
DO i=1,PVar % DOFs
1681
ALLOCATE( Var % Next )
1682
tmpname = ComponentName( PVar % Name, i )
1683
Var % Next = VariableGet( PVar % PrimaryMesh % Variables, tmpname )
1684
Var => Var % Next
1685
END DO
1686
NULLIFY( Var % Next )
1687
Var => Tmp
1688
END IF
1689
1690
!------------------------------------------------------------------------------
1691
! interpolation call
1692
!------------------------------------------------------------------------------
1693
t1 = CPUTime()
1694
1695
UseProjector = ListGetLogical(CurrentModel % Simulation,'Use Mesh Projector',Found)
1696
IF( .NOT. Found ) UseProjector = .TRUE.
1697
1698
IF( PRESENT( MaskName ) ) THEN
1699
CALL Info('VariableGet','Performing masked on-the-fly interpolation',Level=15)
1700
CALL InterpolateMeshToMesh( PVar % PrimaryMesh, &
1701
CurrentModel % Mesh, Var, Variables, MaskName=MaskName )
1702
ELSE IF( UseProjector ) THEN
1703
CALL Info('VariableGet','Performing interpolation with projector',Level=15)
1704
CALL InterpolateMeshToMesh( PVar % PrimaryMesh, &
1705
CurrentModel % Mesh, Var, Variables, Projector=Projector )
1706
ELSE
1707
CALL Info('VariableGet','Performing on-the-fly interpolation',Level=15)
1708
AidVar => VariableGet( CurrentModel % Mesh % Variables, Name, ThisOnly = .TRUE. )
1709
IF( ASSOCIATED( AidVar ) ) THEN
1710
AidVar % Values = 0.0_dp
1711
END IF
1712
CALL InterpolateMeshToMesh( PVar % PrimaryMesh, &
1713
CurrentModel % Mesh, Var, Variables )
1714
END IF
1715
1716
IF( InfoActive( 20 ) ) THEN
1717
AidVar => VariableGet( CurrentModel % Mesh % Variables, Name, ThisOnly = .TRUE. )
1718
PRINT *,'Interpolation range:',TRIM(AidVar % Name),MINVAL(AidVar % Values),MAXVAL( AidVar % Values)
1719
END IF
1720
1721
WRITE( Message,'(A,ES12.3)' ) 'Interpolation time for > '//TRIM(Name)//' < :', CPUTime()-t1
1722
CALL Info( 'VariableGet', Message, Level=7 )
1723
1724
!------------------------------------------------------------------------------
1725
! free the temporary list
1726
!------------------------------------------------------------------------------
1727
DO WHILE( ASSOCIATED( Tmp ) )
1728
Var => Tmp % Next
1729
DEALLOCATE( Tmp )
1730
Tmp => Var
1731
END DO
1732
!------------------------------------------------------------------------------
1733
Var => VariableGet( Variables, Name, ThisOnly=.TRUE. )
1734
Var % Valid = .TRUE.
1735
Var % ValuesChanged = .TRUE.
1736
1737
IF ( Var % Name(1:Var % NameLen) == 'flow solution' ) THEN
1738
Tmp => VariableGet( Variables, 'Velocity 1', ThisOnly=.TRUE. )
1739
IF ( ASSOCIATED(Tmp) ) THEN
1740
Tmp % Valid = .TRUE.
1741
Tmp % ValuesChanged = .TRUE.
1742
END IF
1743
1744
Tmp => VariableGet( Variables, 'Velocity 2', ThisOnly=.TRUE. )
1745
IF ( ASSOCIATED(Tmp) ) THEN
1746
Tmp % Valid = .TRUE.
1747
Tmp % ValuesChanged = .TRUE.
1748
END IF
1749
1750
IF ( Var % DOFs == 4 ) THEN
1751
Tmp => VariableGet( Variables, 'Velocity 3', ThisOnly=.TRUE. )
1752
IF ( ASSOCIATED(Tmp) ) THEN
1753
Tmp % Valid = .TRUE.
1754
Tmp % ValuesChanged = .TRUE.
1755
END IF
1756
END IF
1757
1758
Tmp => VariableGet( Variables, 'Pressure', ThisOnly=.TRUE. )
1759
IF ( ASSOCIATED(Tmp) ) THEN
1760
Tmp % Valid = .TRUE.
1761
Tmp % ValuesChanged = .TRUE.
1762
END IF
1763
ELSE IF ( Var % DOFs > 1 ) THEN
1764
DO i = 1,Var % DOFs
1765
tmpname = ComponentName( Var % Name, i )
1766
Tmp => VariableGet( Variables, tmpname, ThisOnly=.TRUE. )
1767
IF ( ASSOCIATED(Tmp) ) THEN
1768
Tmp % Valid = .TRUE.
1769
Tmp % ValuesChanged = .TRUE.
1770
END IF
1771
END DO
1772
END IF
1773
!------------------------------------------------------------------------------
1774
END FUNCTION VariableGet
1775
!------------------------------------------------------------------------------
1776
1777
1778
!------------------------------------------------------------------------------
1779
FUNCTION ListHead(list) RESULT(head)
1780
!------------------------------------------------------------------------------
1781
TYPE(ValueList_t) :: List
1782
TYPE(ValueListEntry_t), POINTER :: Head
1783
!------------------------------------------------------------------------------
1784
head => List % Head
1785
!------------------------------------------------------------------------------
1786
END FUNCTION ListHead
1787
!------------------------------------------------------------------------------
1788
1789
!------------------------------------------------------------------------------
1790
FUNCTION ListEmpty(list) RESULT(l)
1791
!------------------------------------------------------------------------------
1792
LOGICAL :: L
1793
TYPE(ValueList_t) :: list
1794
!------------------------------------------------------------------------------
1795
L = .NOT.ASSOCIATED(list % head)
1796
!------------------------------------------------------------------------------
1797
END FUNCTION ListEmpty
1798
!------------------------------------------------------------------------------
1799
1800
1801
!------------------------------------------------------------------------------
1802
!> Allocates a new value list.
1803
!------------------------------------------------------------------------------
1804
FUNCTION ListAllocate() RESULT(ptr)
1805
!------------------------------------------------------------------------------
1806
TYPE(ValueList_t), POINTER :: ptr
1807
ALLOCATE( ptr )
1808
ptr % Head => Null()
1809
!------------------------------------------------------------------------------
1810
END FUNCTION ListAllocate
1811
!------------------------------------------------------------------------------
1812
1813
!------------------------------------------------------------------------------
1814
!> Allocates a new value list.
1815
!------------------------------------------------------------------------------
1816
FUNCTION ListEntryAllocate() RESULT(ptr)
1817
!------------------------------------------------------------------------------
1818
TYPE(ValueListEntry_t), POINTER :: ptr
1819
1820
ALLOCATE( ptr )
1821
ptr % PROCEDURE = 0
1822
ptr % TYPE = 0
1823
ptr % NameLen = 0
1824
ptr % LValue = .FALSE.
1825
NULLIFY( ptr % CubicCoeff )
1826
NULLIFY( ptr % Cumulative )
1827
NULLIFY( ptr % Next )
1828
NULLIFY( ptr % FValues )
1829
NULLIFY( ptr % TValues )
1830
NULLIFY( ptr % IValues )
1831
!------------------------------------------------------------------------------
1832
END FUNCTION ListEntryAllocate
1833
!------------------------------------------------------------------------------
1834
1835
1836
!------------------------------------------------------------------------------
1837
!> Deletes a value list.
1838
!------------------------------------------------------------------------------
1839
SUBROUTINE ListDelete( ptr )
1840
!------------------------------------------------------------------------------
1841
TYPE(ValueListEntry_t), POINTER :: ptr
1842
1843
IF ( ASSOCIATED(ptr % CubicCoeff) ) DEALLOCATE(ptr % CubicCoeff)
1844
IF ( ASSOCIATED(ptr % Cumulative) ) DEALLOCATE(ptr % Cumulative)
1845
IF ( ASSOCIATED(ptr % FValues) ) DEALLOCATE(ptr % FValues)
1846
IF ( ASSOCIATED(ptr % TValues) ) DEALLOCATE(ptr % TValues)
1847
IF ( ASSOCIATED(ptr % IValues) ) DEALLOCATE(ptr % IValues)
1848
DEALLOCATE( ptr )
1849
!------------------------------------------------------------------------------
1850
END SUBROUTINE ListDelete
1851
!------------------------------------------------------------------------------
1852
1853
1854
!------------------------------------------------------------------------------
1855
!> Removes an entry from the list by its name.
1856
!------------------------------------------------------------------------------
1857
SUBROUTINE ListRemove( List, Name )
1858
!------------------------------------------------------------------------------
1859
TYPE(ValueList_t) :: List
1860
CHARACTER(LEN=*) :: Name
1861
!------------------------------------------------------------------------------
1862
CHARACTER(LEN=LEN_TRIM(Name)) :: str
1863
INTEGER :: k
1864
LOGICAL :: Found
1865
TYPE(ValueListEntry_t), POINTER :: ptr, prev
1866
!------------------------------------------------------------------------------
1867
IF ( ASSOCIATED(List % Head) ) THEN
1868
k = StringToLowerCase( str,Name,.TRUE. )
1869
ptr => List % Head
1870
Prev => ptr
1871
DO WHILE( ASSOCIATED(ptr) )
1872
IF ( ptr % NameLen == k) THEN
1873
IF(ptr % Name(1:k) == str(1:k) ) THEN
1874
IF ( ASSOCIATED(ptr,List % Head) ) THEN
1875
List % Head => ptr % Next
1876
Prev => List % Head
1877
ELSE
1878
Prev % Next => ptr % Next
1879
END IF
1880
CALL ListDelete(ptr)
1881
EXIT
1882
END IF
1883
END IF
1884
Prev => ptr
1885
ptr => ptr % Next
1886
END DO
1887
END IF
1888
!------------------------------------------------------------------------------
1889
END SUBROUTINE ListRemove
1890
!------------------------------------------------------------------------------
1891
1892
1893
!------------------------------------------------------------------------------
1894
!> Adds an entry to the list by its name and returns a handle to the new entry. If the entry is
1895
!> already existing return the existing one.
1896
!------------------------------------------------------------------------------
1897
FUNCTION ListAdd( List, Name ) RESULT(NEW)
1898
!------------------------------------------------------------------------------
1899
TYPE(ValueList_t), POINTER :: List
1900
CHARACTER(LEN=*) :: Name
1901
TYPE(ValueListEntry_t), POINTER :: new
1902
!------------------------------------------------------------------------------
1903
CHARACTER(LEN=LEN_TRIM(Name)) :: str
1904
INTEGER :: k
1905
LOGICAL :: Found
1906
TYPE(ValueListEntry_t), POINTER :: ptr, prev
1907
!------------------------------------------------------------------------------
1908
Prev => NULL()
1909
Found = .FALSE.
1910
1911
IF(.NOT.ASSOCIATED(List)) List => ListAllocate()
1912
New => ListEntryAllocate()
1913
1914
IF ( ASSOCIATED(List % Head) ) THEN
1915
k = StringToLowerCase( str,Name,.TRUE. )
1916
ptr => List % Head
1917
NULLIFY( prev )
1918
DO WHILE( ASSOCIATED(ptr) )
1919
Found = ptr % NameLen == k
1920
IF(Found) Found = ptr % Name(1:k) == str(1:k)
1921
IF(Found) EXIT
1922
1923
Prev => Ptr
1924
Ptr => Ptr % Next
1925
END DO
1926
1927
IF ( Found ) THEN
1928
New % Next => ptr % Next
1929
IF ( ASSOCIATED( prev ) ) THEN
1930
Prev % Next => New
1931
ELSE
1932
List % Head => New
1933
END IF
1934
CALL ListDelete( Ptr )
1935
ELSE
1936
IF ( ASSOCIATED(prev) ) THEN
1937
prev % next => NEW
1938
ELSE
1939
NEW % Next => List % Head % Next
1940
List % Head % Next => NEW
1941
END IF
1942
END IF
1943
ELSE
1944
List % Head => NEW
1945
END IF
1946
1947
#ifdef DEVEL_LISTCOUNTER
1948
! IF( ASSOCIATED( new ) ) new % Counter = new % Counter + 1
1949
#endif
1950
1951
1952
!------------------------------------------------------------------------------
1953
END FUNCTION ListAdd
1954
!------------------------------------------------------------------------------
1955
1956
1957
!------------------------------------------------------------------------------
1958
!> Sets a namespace string that is used in all list get commands
1959
!> to check for an entry with the namespace, and then continuing to check the one without.
1960
!------------------------------------------------------------------------------
1961
SUBROUTINE ListSetNamespace(str)
1962
!------------------------------------------------------------------------------
1963
CHARACTER(LEN=*) :: str
1964
!------------------------------------------------------------------------------
1965
CHARACTER(LEN=LEN_TRIM(str)) :: str_lcase
1966
!------------------------------------------------------------------------------
1967
INTEGER :: n
1968
!------------------------------------------------------------------------------
1969
n = StringToLowerCase( str_lcase,str,.TRUE. )
1970
1971
CALL Info('ListSetNamespace','Setting namespace to: '//TRIM(str_lcase),Level=15)
1972
1973
NameSpace = str_lcase
1974
!------------------------------------------------------------------------------
1975
END SUBROUTINE ListSetNamespace
1976
!------------------------------------------------------------------------------
1977
1978
!------------------------------------------------------------------------------
1979
!> Returns the active namespace.
1980
!------------------------------------------------------------------------------
1981
FUNCTION ListGetNamespace(str) RESULT(l)
1982
!------------------------------------------------------------------------------
1983
LOGICAL :: l
1984
CHARACTER(:), ALLOCATABLE :: str
1985
!------------------------------------------------------------------------------
1986
IF (ALLOCATED(Namespace)) THEN
1987
l = .TRUE.
1988
str = Namespace
1989
ELSE
1990
l = .FALSE.
1991
END IF
1992
!------------------------------------------------------------------------------
1993
END FUNCTION ListGetNamespace
1994
!------------------------------------------------------------------------------
1995
1996
!------------------------------------------------------------------------------
1997
SUBROUTINE ListPushNamespace(str)
1998
!------------------------------------------------------------------------------
1999
CHARACTER(LEN=*) :: str
2000
!------------------------------------------------------------------------------
2001
LOGICAL :: L
2002
CHARACTER(:), ALLOCATABLE :: tstr
2003
TYPE(String_stack_t), POINTER :: stack
2004
!------------------------------------------------------------------------------
2005
2006
CALL Info('ListPushNameSpace','Adding name space: '//TRIM(str),Level=12)
2007
2008
ALLOCATE(stack)
2009
L = ListGetNameSpace(tstr)
2010
IF(ALLOCATED(tstr)) THEN
2011
stack % name = tstr
2012
ELSE
2013
stack % name = ''
2014
END IF
2015
stack % next => Namespace_stack
2016
Namespace_stack => stack
2017
CALL ListSetNamespace(str)
2018
!------------------------------------------------------------------------------
2019
END SUBROUTINE ListPushNamespace
2020
!------------------------------------------------------------------------------
2021
2022
!------------------------------------------------------------------------------
2023
SUBROUTINE ListPopNamespace( str0 )
2024
!------------------------------------------------------------------------------
2025
CHARACTER(LEN=*), OPTIONAL :: str0
2026
TYPE(String_stack_t), POINTER :: stack
2027
2028
2029
IF(ASSOCIATED(Namespace_stack)) THEN
2030
2031
! This is an optional part aimed to help to code correctly the name stack.
2032
! If one gives the namespace to be popped a Fatal will result if it is a
2033
! wrong namespace.
2034
IF( PRESENT( str0 ) ) THEN
2035
IF( str0 /= Namespace ) THEN
2036
CALL Fatal('ListPopNamespace','Wrong namespace to pop: '&
2037
//TRIM(str0)//' vs '//TRIM(Namespace))
2038
END IF
2039
END IF
2040
2041
Namespace = Namespace_stack % name
2042
2043
CALL Info('ListPopNameSpace','Deleting entry from name space: '&
2044
//TRIM(Namespace),Level=12)
2045
2046
stack => Namespace_stack
2047
Namespace_stack => stack % Next
2048
DEALLOCATE(stack)
2049
ELSE
2050
CALL Info('ListPopNameSpace','No namespace entry to delete',Level=20)
2051
END IF
2052
!------------------------------------------------------------------------------
2053
END SUBROUTINE ListPopNamespace
2054
!------------------------------------------------------------------------------
2055
2056
!------------------------------------------------------------------------------
2057
SUBROUTINE ListPushActivename(str)
2058
!------------------------------------------------------------------------------
2059
CHARACTER(LEN=*) :: str
2060
!------------------------------------------------------------------------------
2061
LOGICAL :: L
2062
TYPE(String_stack_t), POINTER :: stack
2063
!------------------------------------------------------------------------------
2064
ALLOCATE(stack)
2065
stack % name = ListGetActiveName()
2066
stack % next => Activename_stack
2067
Activename_stack => stack
2068
ActiveListName = str
2069
!------------------------------------------------------------------------------
2070
END SUBROUTINE ListPushActiveName
2071
!------------------------------------------------------------------------------
2072
2073
!------------------------------------------------------------------------------
2074
SUBROUTINE ListPopActiveName()
2075
!------------------------------------------------------------------------------
2076
TYPE(String_stack_t), POINTER :: stack
2077
!------------------------------------------------------------------------------
2078
IF(ASSOCIATED(Activename_stack)) THEN
2079
ActiveListName = Activename_stack % name
2080
stack => Activename_stack
2081
Activename_stack => stack % Next
2082
DEALLOCATE(stack)
2083
END IF
2084
!------------------------------------------------------------------------------
2085
END SUBROUTINE ListPopActiveName
2086
!------------------------------------------------------------------------------
2087
2088
!------------------------------------------------------------------------------
2089
FUNCTION ListGetActiveName() RESULT(str)
2090
!------------------------------------------------------------------------------
2091
CHARACTER(:), ALLOCATABLE :: str
2092
!------------------------------------------------------------------------------
2093
IF (ALLOCATED(ActiveListName)) THEN
2094
str = ActiveListName
2095
ELSE
2096
str = ''
2097
END IF
2098
!------------------------------------------------------------------------------
2099
END FUNCTION ListGetActiveName
2100
!------------------------------------------------------------------------------
2101
2102
!------------------------------------------------------------------------------
2103
SUBROUTINE SetNamespaceCheck(L)
2104
!------------------------------------------------------------------------------
2105
LOGICAL :: L
2106
!------------------------------------------------------------------------------
2107
DoNamespaceCheck = L
2108
!------------------------------------------------------------------------------
2109
END SUBROUTINE SetNamespaceCheck
2110
!------------------------------------------------------------------------------
2111
2112
!------------------------------------------------------------------------------
2113
FUNCTION GetNamespaceCheck() RESULT(L)
2114
!------------------------------------------------------------------------------
2115
LOGICAL :: L
2116
!------------------------------------------------------------------------------
2117
L = DoNameSpaceCheck
2118
!------------------------------------------------------------------------------
2119
END FUNCTION GetNamespaceCheck
2120
!------------------------------------------------------------------------------
2121
2122
!------------------------------------------------------------------------------
2123
!> Finds an entry in the list by its name and returns a handle to it.
2124
!------------------------------------------------------------------------------
2125
FUNCTION ListFind( list, name, Found ) RESULT(ptr)
2126
!------------------------------------------------------------------------------
2127
TYPE(ValueListEntry_t), POINTER :: ptr
2128
TYPE(ValueList_t), POINTER :: List
2129
CHARACTER(LEN=*) :: name
2130
LOGICAL, OPTIONAL :: Found
2131
!------------------------------------------------------------------------------
2132
TYPE(String_stack_t), POINTER :: stack
2133
CHARACTER(:), ALLOCATABLE :: stra
2134
CHARACTER(:), ALLOCATABLE :: strn
2135
CHARACTER(LEN=LEN_TRIM(Name)) :: str
2136
!------------------------------------------------------------------------------
2137
INTEGER :: k, k1, n
2138
2139
IF(PRESENT(Found)) Found = .FALSE.
2140
ptr => NULL()
2141
IF(.NOT.ASSOCIATED(List)) RETURN
2142
2143
k = StringToLowerCase( str,Name,.TRUE. )
2144
2145
IF( ListGetnamespace(strn) ) THEN
2146
stack => Namespace_stack
2147
DO WHILE(.TRUE.)
2148
2149
stra = trim(strn)
2150
strn = stra //' '//str(1:k)
2151
2152
k1 = LEN(strn)
2153
ptr => List % Head
2154
DO WHILE( ASSOCIATED(ptr) )
2155
n = ptr % NameLen
2156
IF ( n==k1 ) THEN
2157
IF ( ptr % Name(1:n) == strn ) EXIT
2158
END IF
2159
ptr => ptr % Next
2160
END DO
2161
IF(.NOT.DoNamespaceCheck) EXIT
2162
2163
IF(ASSOCIATED(ptr).OR..NOT.ASSOCIATED(stack)) EXIT
2164
IF(stack % name=='') EXIT
2165
strn = stack % name
2166
stack => stack % next
2167
END DO
2168
END IF
2169
2170
IF ( .NOT. ASSOCIATED(ptr) ) THEN
2171
Ptr => List % Head
2172
DO WHILE( ASSOCIATED(ptr) )
2173
n = ptr % NameLen
2174
IF ( n==k ) THEN
2175
IF ( ptr % Name(1:n) == str(1:n) ) EXIT
2176
END IF
2177
ptr => ptr % Next
2178
END DO
2179
END IF
2180
2181
#ifdef DEVEL_LISTCOUNTER
2182
IF( ASSOCIATED( ptr ) ) THEN
2183
ptr % Counter = ptr % Counter + 1
2184
END IF
2185
#endif
2186
#ifdef DEVEL_LISTUSAGE
2187
IF( ASSOCIATED( ptr ) ) THEN
2188
ptr % Counter = 1
2189
END IF
2190
#endif
2191
2192
IF ( PRESENT(Found) ) THEN
2193
Found = ASSOCIATED(ptr)
2194
ELSE IF (.NOT.ASSOCIATED(ptr) ) THEN
2195
CALL Warn( 'ListFind', ' ' )
2196
WRITE(Message,*) 'Requested property: ', '[',TRIM(Name),'], not found'
2197
CALL Warn( 'ListFind', Message )
2198
CALL Warn( 'ListFind', ' ' )
2199
END IF
2200
!------------------------------------------------------------------------------
2201
END FUNCTION ListFind
2202
!------------------------------------------------------------------------------
2203
2204
2205
!------------------------------------------------------------------------------
2206
!> Finds an entry in the list by its name and returns a handle to it.
2207
!------------------------------------------------------------------------------
2208
SUBROUTINE ListRename( list, name, name2, Found )
2209
!------------------------------------------------------------------------------
2210
TYPE(ValueList_t), POINTER :: List
2211
CHARACTER(LEN=*) :: name, name2
2212
LOGICAL, OPTIONAL :: Found
2213
!------------------------------------------------------------------------------
2214
TYPE(ValueListEntry_t), POINTER :: ptr
2215
CHARACTER(:), ALLOCATABLE :: strn
2216
CHARACTER(LEN=LEN_TRIM(Name)) :: str
2217
CHARACTER(LEN=LEN_TRIM(Name2)) :: str2
2218
INTEGER :: k, k2, n
2219
2220
IF(PRESENT(Found)) Found = .FALSE.
2221
2222
ptr => NULL()
2223
IF(.NOT.ASSOCIATED(List)) RETURN
2224
2225
k = StringToLowerCase( str,Name,.TRUE. )
2226
2227
Ptr => List % Head
2228
DO WHILE( ASSOCIATED(ptr) )
2229
n = ptr % NameLen
2230
IF ( n==k ) THEN
2231
IF ( ptr % Name(1:n) == str(1:n) ) EXIT
2232
END IF
2233
ptr => ptr % Next
2234
END DO
2235
2236
IF( ASSOCIATED( ptr ) ) THEN
2237
k2 = StringToLowerCase( str2,Name2,.TRUE. )
2238
ptr % Name = str2(1:k2)
2239
ptr % NameLen = k2
2240
!PRINT *,'renaming >'//str(1:k)//'< to >'//str2(1:k2)//'<', k, k2
2241
END IF
2242
2243
IF ( PRESENT(Found) ) THEN
2244
Found = ASSOCIATED(ptr)
2245
ELSE IF (.NOT.ASSOCIATED(ptr) ) THEN
2246
CALL Warn( 'ListRename', ' ' )
2247
WRITE(Message,*) 'Requested property: ', '[',TRIM(Name),'], not found'
2248
CALL Warn( 'ListRename', Message )
2249
CALL Warn( 'ListRename', ' ' )
2250
END IF
2251
!------------------------------------------------------------------------------
2252
END SUBROUTINE ListRename
2253
!------------------------------------------------------------------------------
2254
2255
2256
!------------------------------------------------------------------------------
2257
!> Rename all given keywords in BC section.
2258
!------------------------------------------------------------------------------
2259
SUBROUTINE ListRenameAllBC( Model, Name, Name2 )
2260
!------------------------------------------------------------------------------
2261
TYPE(Model_t) :: Model
2262
CHARACTER(LEN=*) :: Name, Name2
2263
LOGICAL :: Found
2264
INTEGER :: bc, n
2265
2266
n = 0
2267
DO bc = 1,Model % NumberOfBCs
2268
CALL ListRename( Model % BCs(bc) % Values, Name, Name2, Found )
2269
IF( Found ) n = n + 1
2270
END DO
2271
IF( n > 0 ) CALL Info('ListRenameAllBCs',&
2272
'"'//TRIM(Name)//'" renamed to "'//TRIM(Name2)//'" on '//I2S(n)//' BCs',Level=6)
2273
2274
!------------------------------------------------------------------------------
2275
END SUBROUTINE ListRenameAllBC
2276
!------------------------------------------------------------------------------
2277
2278
!------------------------------------------------------------------------------
2279
!> Rename all given keywords in body force section.
2280
!------------------------------------------------------------------------------
2281
SUBROUTINE ListRenameAllBodyForce( Model, Name, Name2 )
2282
!------------------------------------------------------------------------------
2283
TYPE(Model_t) :: Model
2284
CHARACTER(LEN=*) :: Name, Name2
2285
LOGICAL :: Found
2286
INTEGER :: bc, n
2287
2288
n = 0
2289
DO bc = 1,Model % NumberOfBodyForces
2290
CALL ListRename( Model % BodyForces(bc) % Values, Name, Name2, Found )
2291
IF( Found ) n = n + 1
2292
END DO
2293
IF( n > 0 ) CALL Info('ListRenameAllBodyForces',&
2294
'"'//TRIM(Name)//'" renamed to "'//TRIM(Name2)//'" on '//I2S(n)//' BCs',Level=6)
2295
2296
!------------------------------------------------------------------------------
2297
END SUBROUTINE ListRenameAllBodyForce
2298
!------------------------------------------------------------------------------
2299
2300
2301
!------------------------------------------------------------------------------
2302
!> Just checks if a entry is present in the list.
2303
!------------------------------------------------------------------------------
2304
FUNCTION ListCheckPresent( List,Name ) RESULT(Found)
2305
!------------------------------------------------------------------------------
2306
TYPE(ValueList_t), POINTER :: List
2307
CHARACTER(LEN=*) :: Name
2308
LOGICAL :: Found
2309
!------------------------------------------------------------------------------
2310
TYPE(ValueListEntry_t), POINTER :: ptr
2311
!------------------------------------------------------------------------------
2312
ptr => ListFind(List,Name,Found)
2313
!------------------------------------------------------------------------------
2314
END FUNCTION ListCheckPresent
2315
!------------------------------------------------------------------------------
2316
2317
2318
!-----------------------------------------------------------------------------
2319
!> Finds an entry in the list by its name and returns a handle to it.
2320
!> This one just finds a keyword with the same start as specified by 'name'.
2321
!------------------------------------------------------------------------------
2322
FUNCTION ListFindPrefix( list, name, Found) RESULT(ptr)
2323
!------------------------------------------------------------------------------
2324
TYPE(ValueListEntry_t), POINTER :: ptr
2325
TYPE(ValueList_t), POINTER :: list
2326
CHARACTER(LEN=*) :: name
2327
LOGICAL, OPTIONAL :: Found
2328
!------------------------------------------------------------------------------
2329
TYPE(String_stack_t), POINTER :: stack
2330
CHARACTER(:), ALLOCATABLE :: strn,stra
2331
CHARACTER(LEN=LEN_TRIM(Name)) :: str
2332
!------------------------------------------------------------------------------
2333
INTEGER :: k, k1, n, m
2334
2335
ptr => NULL()
2336
IF(.NOT.ASSOCIATED(List)) RETURN
2337
2338
k = StringToLowerCase( str,Name,.TRUE. )
2339
IF ( ListGetNamespace(strn) ) THEN
2340
stack => Namespace_stack
2341
DO WHILE(.TRUE.)
2342
stra = trim(strn)
2343
strn = stra //' '//str(1:k)
2344
2345
k1 = LEN(strn)
2346
ptr => List % Head
2347
DO WHILE( ASSOCIATED(ptr) )
2348
n = ptr % NameLen
2349
IF ( n >= k1 ) THEN
2350
IF ( ptr % Name(1:k1) == strn ) EXIT
2351
END IF
2352
ptr => ptr % Next
2353
END DO
2354
IF(.NOT.DoNamespaceCheck) EXIT
2355
2356
IF(ASSOCIATED(ptr).OR..NOT.ASSOCIATED(stack)) EXIT
2357
IF(stack % name=='') EXIT
2358
strn = stack % name
2359
stack => stack % next
2360
END DO
2361
END IF
2362
2363
IF ( .NOT. ASSOCIATED(ptr) ) THEN
2364
Ptr => List % Head
2365
DO WHILE( ASSOCIATED(ptr) )
2366
n = ptr % NameLen
2367
IF ( n >= k ) THEN
2368
IF ( ptr % Name(1:k) == str(1:k) ) EXIT
2369
END IF
2370
ptr => ptr % Next
2371
END DO
2372
END IF
2373
2374
IF ( PRESENT(Found) ) THEN
2375
Found = ASSOCIATED(ptr)
2376
ELSE IF (.NOT.ASSOCIATED(ptr) ) THEN
2377
CALL Warn( 'ListFindPrefix', ' ' )
2378
WRITE(Message,*) 'Requested prefix: ', '[',TRIM(Name),'], not found'
2379
CALL Warn( 'ListFindPrefix', Message )
2380
CALL Warn( 'ListFindPrefix', ' ' )
2381
END IF
2382
!------------------------------------------------------------------------------
2383
END FUNCTION ListFindPrefix
2384
!------------------------------------------------------------------------------
2385
2386
2387
!------------------------------------------------------------------------------
2388
!> Finds an entry in the list by its name and returns a handle to it.
2389
!> This one just finds a keyword with the same end as specified by 'name'.
2390
!------------------------------------------------------------------------------
2391
FUNCTION ListFindSuffix( list, name, Found) RESULT(ptr)
2392
!------------------------------------------------------------------------------
2393
TYPE(ValueListEntry_t), POINTER :: ptr
2394
TYPE(ValueList_t), POINTER :: list
2395
CHARACTER(LEN=*) :: name
2396
LOGICAL, OPTIONAL :: Found
2397
!------------------------------------------------------------------------------
2398
CHARACTER(LEN=LEN_TRIM(Name)) :: str
2399
!------------------------------------------------------------------------------
2400
INTEGER :: k, k1, n, m
2401
2402
ptr => Null()
2403
IF(.NOT.ASSOCIATED(List)) RETURN
2404
2405
k = StringToLowerCase( str,Name,.TRUE. )
2406
Ptr => List % Head
2407
DO WHILE( ASSOCIATED(ptr) )
2408
n = ptr % NameLen
2409
IF ( n >= k ) THEN
2410
IF ( ptr % Name(n-k+1:n) == str(1:k) ) EXIT
2411
END IF
2412
ptr => ptr % Next
2413
END DO
2414
2415
IF ( PRESENT(Found) ) THEN
2416
Found = ASSOCIATED(ptr)
2417
ELSE IF (.NOT.ASSOCIATED(ptr) ) THEN
2418
CALL Warn( 'ListFindSuffix', ' ' )
2419
WRITE(Message,*) 'Requested suffix: ', '[',TRIM(Name),'], not found'
2420
CALL Warn( 'ListFindSuffix', Message )
2421
CALL Warn( 'ListFindSuffix', ' ' )
2422
END IF
2423
!------------------------------------------------------------------------------
2424
END FUNCTION ListFindSuffix
2425
!------------------------------------------------------------------------------
2426
2427
2428
2429
!------------------------------------------------------------------------------
2430
!> Check if the suffix exists in the list.
2431
!------------------------------------------------------------------------------
2432
FUNCTION ListCheckSuffix( List, Name ) RESULT(Found)
2433
!------------------------------------------------------------------------------
2434
TYPE(ValueList_t), POINTER :: List
2435
CHARACTER(LEN=*) :: Name
2436
LOGICAL :: Found
2437
TYPE(ValuelistEntry_t), POINTER :: ptr
2438
2439
ptr => ListFindSuffix( List, Name, Found )
2440
!------------------------------------------------------------------------------
2441
END FUNCTION ListCheckSuffix
2442
!------------------------------------------------------------------------------
2443
2444
2445
!------------------------------------------------------------------------------
2446
!> Check if the keyword is with the given suffix is present in any boundary condition.
2447
!------------------------------------------------------------------------------
2448
FUNCTION ListCheckSuffixAnyBC( Model, Name ) RESULT(Found)
2449
!------------------------------------------------------------------------------
2450
TYPE(Model_t) :: Model
2451
CHARACTER(LEN=*) :: Name
2452
LOGICAL :: Found
2453
INTEGER :: bc
2454
TYPE(ValuelistEntry_t), POINTER :: ptr
2455
2456
Found = .FALSE.
2457
DO bc = 1,Model % NumberOfBCs
2458
ptr => ListFindSuffix( Model % BCs(bc) % Values, Name, Found )
2459
IF( Found ) EXIT
2460
END DO
2461
!------------------------------------------------------------------------------
2462
END FUNCTION ListCheckSuffixAnyBC
2463
!------------------------------------------------------------------------------
2464
2465
!------------------------------------------------------------------------------
2466
!> Check if the keyword is with the given suffix is present in any body.
2467
!------------------------------------------------------------------------------
2468
FUNCTION ListCheckSuffixAnyBody( Model, Name ) RESULT(Found)
2469
!------------------------------------------------------------------------------
2470
TYPE(Model_t) :: Model
2471
CHARACTER(LEN=*) :: Name
2472
LOGICAL :: Found
2473
INTEGER :: body_id
2474
TYPE(ValuelistEntry_t), POINTER :: ptr
2475
2476
Found = .FALSE.
2477
DO body_id = 1,Model % NumberOfBodies
2478
ptr => ListFindSuffix( Model % Bodies(body_id) % Values, Name, Found )
2479
IF( Found ) EXIT
2480
END DO
2481
!------------------------------------------------------------------------------
2482
END FUNCTION ListCheckSuffixAnyBody
2483
!------------------------------------------------------------------------------
2484
2485
!------------------------------------------------------------------------------
2486
!> Check if the keyword is with the given suffix is present in any material.
2487
!------------------------------------------------------------------------------
2488
FUNCTION ListCheckSuffixAnyMaterial( Model, Name ) RESULT(Found)
2489
!------------------------------------------------------------------------------
2490
TYPE(Model_t) :: Model
2491
CHARACTER(LEN=*) :: Name
2492
LOGICAL :: Found
2493
INTEGER :: mat_id
2494
TYPE(ValuelistEntry_t), POINTER :: ptr
2495
2496
Found = .FALSE.
2497
DO mat_id = 1,Model % NumberOfMaterials
2498
ptr => ListFindSuffix( Model % Materials(mat_id) % Values, Name, Found )
2499
IF( Found ) EXIT
2500
END DO
2501
!------------------------------------------------------------------------------
2502
END FUNCTION ListCheckSuffixAnyMaterial
2503
!------------------------------------------------------------------------------
2504
2505
!------------------------------------------------------------------------------
2506
!> Check if the keyword is with the given suffix is present in any body force.
2507
!------------------------------------------------------------------------------
2508
FUNCTION ListCheckSuffixAnyBodyForce( Model, Name ) RESULT(Found)
2509
!------------------------------------------------------------------------------
2510
TYPE(Model_t) :: Model
2511
CHARACTER(LEN=*) :: Name
2512
LOGICAL :: Found
2513
INTEGER :: bf_id
2514
TYPE(ValuelistEntry_t), POINTER :: ptr
2515
2516
Found = .FALSE.
2517
DO bf_id = 1,Model % NumberOfBodyForces
2518
ptr => ListFindSuffix( Model % BodyForces(bf_id) % Values, Name, Found )
2519
IF( Found ) EXIT
2520
END DO
2521
!------------------------------------------------------------------------------
2522
END FUNCTION ListCheckSuffixAnyBodyForce
2523
!------------------------------------------------------------------------------
2524
2525
2526
!------------------------------------------------------------------------------
2527
!> Finds an entry related to vector keyword of type "name" or "name i", i=1,2,3.
2528
!> This could save time since it will detect at one sweep whether the keyword
2529
!> for a vector is given, and whether it is componentwise or not.
2530
!> There is a caveat since currently the "i" is not checked and possibly
2531
!> the user could mix the formats and the chosen one would be random.
2532
!------------------------------------------------------------------------------
2533
FUNCTION ListFindVectorPrefix( list, name, ComponentWise,Found ) RESULT(ptr)
2534
!------------------------------------------------------------------------------
2535
TYPE(ValueListEntry_t), POINTER :: ptr
2536
TYPE(ValueList_t), POINTER :: list
2537
CHARACTER(LEN=*) :: name
2538
LOGICAL :: ComponentWise
2539
LOGICAL, OPTIONAL :: Found
2540
!------------------------------------------------------------------------------
2541
TYPE(String_stack_t), POINTER :: stack
2542
CHARACTER(:), ALLOCATABLE :: strn
2543
CHARACTER(LEN=LEN_TRIM(Name)) :: str
2544
!------------------------------------------------------------------------------
2545
INTEGER :: k, k1, n, m
2546
2547
ptr => NULL()
2548
IF(.NOT.ASSOCIATED(List)) RETURN
2549
2550
k = StringToLowerCase( str,Name,.TRUE. )
2551
2552
IF ( ListGetNamespace(strn) ) THEN
2553
stack => Namespace_stack
2554
DO WHILE(.TRUE.)
2555
strn = TRIM(strn) //' '//str(1:k)
2556
k1 = LEN(strn)
2557
ptr => List % Head
2558
DO WHILE( ASSOCIATED(ptr) )
2559
n = ptr % NameLen
2560
IF ( n == k1 ) THEN
2561
IF ( ptr % Name(1:k1) == strn ) THEN
2562
ComponentWise = .FALSE.
2563
EXIT
2564
END IF
2565
ELSE IF( n == k1 + 2 ) THEN
2566
IF ( ptr % Name(1:k1+1) == strn//' ' ) THEN
2567
ComponentWise = .TRUE.
2568
EXIT
2569
END IF
2570
END IF
2571
ptr => ptr % Next
2572
END DO
2573
IF(.NOT.DoNamespaceCheck) EXIT
2574
2575
IF(ASSOCIATED(ptr).OR..NOT.ASSOCIATED(stack)) EXIT
2576
IF(stack % name=='') EXIT
2577
strn = stack % name
2578
stack => stack % next
2579
END DO
2580
END IF
2581
2582
IF ( .NOT. ASSOCIATED(ptr) ) THEN
2583
Ptr => List % Head
2584
DO WHILE( ASSOCIATED(ptr) )
2585
n = ptr % NameLen
2586
IF ( n == k ) THEN
2587
IF ( ptr % Name(1:k) == str(1:k) ) THEN
2588
ComponentWise = .FALSE.
2589
EXIT
2590
END IF
2591
ELSE IF( n == k + 2 ) THEN
2592
IF ( ptr % Name(1:k+1) == str(1:k)//' ' ) THEN
2593
ComponentWise = .TRUE.
2594
EXIT
2595
END IF
2596
END IF
2597
ptr => ptr % Next
2598
END DO
2599
END IF
2600
2601
IF ( PRESENT(Found) ) THEN
2602
Found = ASSOCIATED(ptr)
2603
ELSE IF (.NOT.ASSOCIATED(ptr) ) THEN
2604
CALL Warn( 'ListFindVectorPrefix', ' ' )
2605
WRITE(Message,*) 'Requested vector prefix: ', '[',TRIM(Name),'], not found'
2606
CALL Warn( 'ListFindVectorPrefix', Message )
2607
CALL Warn( 'ListFindVectorPrefix', ' ' )
2608
END IF
2609
!------------------------------------------------------------------------------
2610
END FUNCTION ListFindVectorPrefix
2611
!------------------------------------------------------------------------------
2612
2613
2614
2615
!------------------------------------------------------------------------------
2616
!> Finds a keyword with the given basename and normalizes it with a
2617
!> constant coefficients for all future request of the keyword.
2618
!------------------------------------------------------------------------------
2619
SUBROUTINE ListSetCoefficients( list, name, coeff )
2620
!------------------------------------------------------------------------------
2621
TYPE(ValueList_t), POINTER :: list
2622
CHARACTER(LEN=*) :: name
2623
REAL(KIND=dp) :: coeff
2624
!------------------------------------------------------------------------------
2625
TYPE(ValueListEntry_t), POINTER :: ptr, ptr2
2626
CHARACTER(LEN=LEN_TRIM(Name)) :: str
2627
INTEGER :: k, k1, n, n2, m
2628
2629
IF(.NOT.ASSOCIATED(List)) RETURN
2630
2631
k = StringToLowerCase( str,Name,.TRUE. )
2632
2633
Ptr => list % Head
2634
DO WHILE( ASSOCIATED(ptr) )
2635
IF( ptr % disttag ) THEN
2636
WRITE( Message,'(A,ES12.5)') 'Normalizing > '//&
2637
TRIM( ptr2 % Name )// ' < by ',Coeff
2638
CALL Info('ListSetCoefficients',Message,Level=7)
2639
ptr % Coeff = Coeff
2640
ptr => ptr % Next
2641
CYCLE
2642
END IF
2643
2644
n = ptr % NameLen
2645
IF ( n >= k ) THEN
2646
! Did we find a keyword which has the correct suffix?
2647
IF ( ptr % Name(n-k+1:n) == str(1:k) ) THEN
2648
Ptr2 => list % Head
2649
DO WHILE( ASSOCIATED(ptr2) )
2650
n2 = ptr2 % NameLen
2651
IF( n2 + k <= n ) THEN
2652
2653
! Did we find the corresponding keyword without the suffix?
2654
IF ( ptr2 % Name(1:n2) == ptr % Name(1:n2) ) THEN
2655
WRITE( Message,'(A,ES12.5)') 'Normalizing > '//&
2656
TRIM( ptr2 % Name )// ' < by ',Coeff
2657
CALL Info('ListSetCoefficients',Message,Level=7)
2658
ptr2 % Coeff = Coeff
2659
EXIT
2660
END IF
2661
2662
END IF
2663
ptr2 => ptr2 % Next
2664
END DO
2665
END IF
2666
END IF
2667
ptr => ptr % Next
2668
END DO
2669
!------------------------------------------------------------------------------
2670
END SUBROUTINE ListSetCoefficients
2671
!------------------------------------------------------------------------------
2672
2673
2674
!------------------------------------------------------------------------------
2675
!> Add a parameter tag to an existing keyword. By construction we know this
2676
!> should exist.
2677
!------------------------------------------------------------------------------
2678
SUBROUTINE ListParTagKeyword( List,Name,partag )
2679
!------------------------------------------------------------------------------
2680
TYPE(ValueList_t), POINTER :: List
2681
CHARACTER(LEN=*) :: Name
2682
INTEGER :: partag
2683
!------------------------------------------------------------------------------
2684
TYPE(ValueListEntry_t), POINTER :: ptr
2685
LOGICAL :: Found
2686
!------------------------------------------------------------------------------
2687
ptr => ListFind( List, Name, Found )
2688
IF(.NOT. Found) THEN
2689
CALL Fatal('ListParTagKeyword','Cannot add tag to non-existing keyword: '//TRIM(Name))
2690
END IF
2691
Ptr % partag = partag
2692
2693
END SUBROUTINE ListParTagKeyword
2694
!------------------------------------------------------------------------------
2695
2696
2697
!------------------------------------------------------------------------------
2698
!> Add tag to distribute value of existing keyword.
2699
!------------------------------------------------------------------------------
2700
SUBROUTINE ListDistTagKeyword( List,Name )
2701
!------------------------------------------------------------------------------
2702
TYPE(ValueList_t), POINTER :: List
2703
CHARACTER(LEN=*) :: Name
2704
!------------------------------------------------------------------------------
2705
TYPE(ValueListEntry_t), POINTER :: ptr
2706
LOGICAL :: Found
2707
!------------------------------------------------------------------------------
2708
ptr => ListFind( List, Name, Found )
2709
IF(.NOT. Found) THEN
2710
CALL Fatal('ListDistTagKeyword','Cannot add tag to non-existing keyword: '//TRIM(Name))
2711
END IF
2712
Ptr % disttag = .TRUE.
2713
2714
END SUBROUTINE ListDistTagKeyword
2715
!------------------------------------------------------------------------------
2716
2717
2718
!----------------------------------------------------------------
2719
!> Given a suffix tag keyword that have the keyword without the
2720
!> suffix. If the "tagwei" flag is True set the tag related to the
2721
!> weight computation, if it is False set integer tag related to parameter
2722
!> control.
2723
!----------------------------------------------------------------
2724
SUBROUTINE ListTagKeywords( Model, suffix, tagwei, Found )
2725
!----------------------------------------------------------------
2726
TYPE(Model_t) :: Model
2727
CHARACTER(LEN=*) :: suffix
2728
LOGICAL :: tagwei
2729
LOGICAL :: Found
2730
!----------------------------------------------------------------
2731
INTEGER :: i,cnt
2732
2733
CALL Info('ListTagKeywords','Setting weight for keywords!',Level=20)
2734
cnt = 0
2735
2736
CALL ListTagEntry(Model % Simulation, suffix, tagwei, cnt )
2737
CALL ListTagEntry(Model % Constants, suffix, tagwei, cnt )
2738
DO i=1,Model % NumberOfEquations
2739
CALL ListTagEntry(Model % Equations(i) % Values, suffix, tagwei, cnt )
2740
END DO
2741
DO i=1,Model % NumberOfComponents
2742
CALL ListTagEntry(Model % Components(i) % Values, suffix, tagwei, cnt )
2743
END DO
2744
DO i=1,Model % NumberOfBodyForces
2745
CALL ListTagEntry(Model % BodyForces(i) % Values, suffix, tagwei, cnt )
2746
END DO
2747
DO i=1,Model % NumberOfICs
2748
CALL ListTagEntry(Model % ICs(i) % Values, suffix, tagwei, cnt )
2749
END DO
2750
DO i=1,Model % NumberOfBCs
2751
CALL ListTagEntry(Model % BCs(i) % Values, suffix, tagwei, cnt )
2752
END DO
2753
DO i=1,Model % NumberOfMaterials
2754
CALL ListTagEntry(Model % Materials(i) % Values, suffix, tagwei, cnt )
2755
END DO
2756
DO i=1,Model % NumberOfBoundaries
2757
CALL ListTagEntry(Model % Boundaries(i) % Values, suffix, tagwei, cnt )
2758
END DO
2759
DO i=1,Model % NumberOfSolvers
2760
CALL ListTagEntry(Model % Solvers(i) % Values, suffix, tagwei, cnt )
2761
END DO
2762
2763
Found = ( cnt > 0 )
2764
2765
IF( Found ) THEN
2766
CALL Info('ListTagKeywords',&
2767
'Tagged '//I2S(cnt)//' parameters with suffix: '//TRIM(suffix),Level=7)
2768
ELSE
2769
CALL Info('ListTagKeywords','No parameters width suffix: '//TRIM(suffix),Level=20)
2770
END IF
2771
2772
CONTAINS
2773
2774
!------------------------------------------------------------------------------
2775
SUBROUTINE ListTagEntry( list, name, tagwei, cnt )
2776
!------------------------------------------------------------------------------
2777
TYPE(ValueList_t), POINTER :: list
2778
CHARACTER(LEN=*) :: name
2779
LOGICAL :: tagwei
2780
INTEGER :: cnt
2781
!------------------------------------------------------------------------------
2782
TYPE(ValueListEntry_t), POINTER :: ptr, ptr2
2783
CHARACTER(LEN=LEN_TRIM(Name)) :: str
2784
INTEGER :: k, k1, n, n2, m, partag
2785
2786
IF(.NOT.ASSOCIATED(List)) RETURN
2787
2788
m = 0
2789
k = StringToLowerCase( str,Name,.TRUE. )
2790
2791
Ptr => list % Head
2792
DO WHILE( ASSOCIATED(ptr) )
2793
n = ptr % NameLen
2794
IF ( n >= k ) THEN
2795
! Did we find a keyword which has the correct suffix?
2796
IF ( ptr % Name(n-k+1:n) == str(1:k) ) THEN
2797
Ptr2 => list % Head
2798
DO WHILE( ASSOCIATED(ptr2) )
2799
n2 = ptr2 % NameLen
2800
IF( n2 + k <= n ) THEN
2801
! Did we find the corresponding keyword without the suffix?
2802
IF ( ptr2 % Name(1:n2) == ptr % Name(1:n2) ) THEN
2803
IF( tagwei ) THEN
2804
ptr2 % disttag = ptr % Lvalue
2805
m = m + 1
2806
WRITE( Message,'(A)') 'Adding dist tag to "'//TRIM( ptr2 % Name )//'"'
2807
CALL Info('ListTagKeywords',Message,Level=15)
2808
ELSE
2809
partag = ptr % IValues(1)
2810
IF(partag<1) THEN
2811
CALL Warn('ListTagKeywords','Positive integer expected for parameter tag!')
2812
ELSE
2813
WRITE( Message,'(A)') 'Adding tag '//I2S(partag)//&
2814
' to "'//TRIM( ptr2 % Name )//'"'
2815
CALL Info('ListTagKeywords',Message,Level=15)
2816
ptr2 % partag = partag
2817
m = m + 1
2818
END IF
2819
END IF
2820
END IF
2821
END IF
2822
ptr2 => ptr2 % Next
2823
END DO
2824
END IF
2825
END IF
2826
ptr => ptr % Next
2827
END DO
2828
2829
IF( m > 0 ) THEN
2830
CALL Info('ListTagKeywords',&
2831
'Tagged '//I2S(m)//' parameters in list',Level=15)
2832
END IF
2833
cnt = cnt + m
2834
2835
END SUBROUTINE ListTagEntry
2836
2837
END SUBROUTINE ListTagKeywords
2838
2839
2840
2841
!----------------------------------------------------------------
2842
!> Given a suffix tag keyword that have the keyword without the
2843
!> suffix. If the "tagwei" flag is True set the tag related to the
2844
!> weight computation, if it is False set tag related to parameter
2845
!> control.
2846
!----------------------------------------------------------------
2847
FUNCTION ListTagCount( Model, tagwei ) RESULT ( cnt )
2848
!----------------------------------------------------------------
2849
TYPE(Model_t) :: Model
2850
LOGICAL :: tagwei
2851
INTEGER :: cnt
2852
!----------------------------------------------------------------
2853
INTEGER :: i
2854
2855
IF( tagwei ) THEN
2856
CALL Info('ListTagCount','Counting tags for keyword normalization!',Level=12)
2857
ELSE
2858
CALL Info('ListTagCount','Counting tags for keyword variation!',Level=12)
2859
END IF
2860
2861
! Only the following lists have been created for weights.
2862
! We could add more, but only lists that have elements associated to them.
2863
cnt = 0
2864
DO i=1,Model % NumberOfBCs
2865
CALL ListTagCnt(Model % BCs(i) % Values, tagwei, cnt )
2866
END DO
2867
DO i=1,Model % NumberOfMaterials
2868
CALL ListTagCnt(Model % Materials(i) % Values, tagwei, cnt )
2869
END DO
2870
DO i=1,Model % NumberOfBodyForces
2871
CALL ListTagCnt(Model % BodyForces(i) % Values, tagwei, cnt )
2872
END DO
2873
DO i=1,Model % NumberOfBodies
2874
CALL ListTagCnt(Model % Bodies(i) % Values, tagwei, cnt )
2875
END DO
2876
IF(tagwei) THEN
2877
IF(cnt>0) CALL Info('ListTagCount','Found number of normalized keywords: '//I2S(cnt),Level=6)
2878
RETURN
2879
END IF
2880
2881
CALL ListTagCnt(Model % Simulation, tagwei, cnt )
2882
CALL ListTagCnt(Model % Constants, tagwei, cnt )
2883
DO i=1,Model % NumberOfEquations
2884
CALL ListTagCnt(Model % Equations(i) % Values, tagwei, cnt )
2885
END DO
2886
DO i=1,Model % NumberOfComponents
2887
CALL ListTagCnt(Model % Components(i) % Values, tagwei, cnt )
2888
END DO
2889
DO i=1,Model % NumberOfICs
2890
CALL ListTagCnt(Model % ICs(i) % Values, tagwei, cnt )
2891
END DO
2892
DO i=1,Model % NumberOfBoundaries
2893
CALL ListTagCnt(Model % Boundaries(i) % Values, tagwei, cnt )
2894
END DO
2895
DO i=1,Model % NumberOfSolvers
2896
CALL ListTagCnt(Model % Solvers(i) % Values, tagwei, cnt )
2897
END DO
2898
2899
IF(cnt>0) CALL Info('ListTagCount','Found number of parameters: '//I2S(cnt),Level=6)
2900
2901
CONTAINS
2902
2903
!------------------------------------------------------------------------------
2904
SUBROUTINE ListTagCnt( list, tagwei, cnt )
2905
!------------------------------------------------------------------------------
2906
TYPE(ValueList_t), POINTER :: list
2907
LOGICAL :: tagwei
2908
INTEGER :: cnt
2909
!------------------------------------------------------------------------------
2910
TYPE(ValueListEntry_t), POINTER :: ptr
2911
INTEGER :: m
2912
2913
IF(.NOT.ASSOCIATED(List)) RETURN
2914
2915
m = 0
2916
2917
Ptr => list % Head
2918
DO WHILE( ASSOCIATED(ptr) )
2919
IF( tagwei ) THEN
2920
IF( ptr % disttag ) m = m + 1
2921
ELSE
2922
IF( ptr % partag > 0 ) m = m + 1
2923
END IF
2924
ptr => ptr % Next
2925
END DO
2926
2927
IF( m > 0 ) THEN
2928
CALL Info('ListTagParameters',&
2929
'Tagged number of parameters in list: '//I2S(m),Level=15)
2930
END IF
2931
cnt = cnt + m
2932
2933
END SUBROUTINE ListTagCnt
2934
2935
END FUNCTION ListTagCount
2936
2937
2938
!----------------------------------------------------------------
2939
!> Given any real keyword that is tagged to be a design parameter
2940
!> multiply it with the given coefficient. This assumes that the
2941
!> List operatiorsn use the "coeff" field to scale the real valued
2942
!> keywords. The intended use for this is to make it easier to
2943
!> variations for optimization, control and sensitivity analysis.
2944
!----------------------------------------------------------------
2945
SUBROUTINE ListSetParameters( Model, partag, val, mult, Found )
2946
!----------------------------------------------------------------
2947
TYPE(Model_t) :: Model
2948
INTEGER :: partag
2949
REAL(KIND=dp) :: val
2950
LOGICAL :: mult
2951
LOGICAL :: Found
2952
!----------------------------------------------------------------
2953
INTEGER :: i,cnt
2954
TYPE(Mesh_t), POINTER :: Mesh
2955
REAL(KIND=dp), POINTER :: Weights(:)
2956
2957
CALL Info('ListSetParameters',&
2958
'Setting variation to parameter: '//I2S(partag),Level=12)
2959
cnt = 0
2960
2961
Weights => NULL()
2962
Mesh => Model % Mesh
2963
2964
DO i=1,Model % NumberOfBodies
2965
Weights => Mesh % BodyWeight
2966
CALL ListSetTagged(Model % Bodies(i) % Values, partag, val, mult, cnt )
2967
END DO
2968
DO i=1,Model % NumberOfBodyForces
2969
Weights => Mesh % BodyForceWeight
2970
CALL ListSetTagged(Model % BodyForces(i) % Values, partag, val, mult, cnt )
2971
END DO
2972
DO i=1,Model % NumberOfBCs
2973
Weights => Mesh % BCWeight
2974
CALL ListSetTagged(Model % BCs(i) % Values, partag, val, mult, cnt )
2975
END DO
2976
DO i=1,Model % NumberOfMaterials
2977
Weights => Mesh % MaterialWeight
2978
CALL ListSetTagged(Model % Materials(i) % Values, partag, val, mult, cnt )
2979
END DO
2980
2981
IF( partag > 0 ) THEN
2982
CALL ListSetTagged(Model % Simulation, partag, val, mult, cnt )
2983
CALL ListSetTagged(Model % Constants, partag, val, mult, cnt )
2984
DO i=1,Model % NumberOfEquations
2985
CALL ListSetTagged(Model % Equations(i) % Values, partag, val, mult, cnt )
2986
END DO
2987
DO i=1,Model % NumberOfComponents
2988
CALL ListSetTagged(Model % Components(i) % Values, partag, val, mult, cnt )
2989
END DO
2990
DO i=1,Model % NumberOfICs
2991
CALL ListSetTagged(Model % ICs(i) % Values, partag, val, mult, cnt )
2992
END DO
2993
DO i=1,Model % NumberOfBoundaries
2994
CALL ListSetTagged(Model % Boundaries(i) % Values, partag, val, mult, cnt )
2995
END DO
2996
DO i=1,Model % NumberOfSolvers
2997
CALL ListSetTagged(Model % Solvers(i) % Values, partag, val, mult, cnt )
2998
END DO
2999
END IF
3000
3001
10 Found = ( cnt > 0 )
3002
3003
IF( Found ) THEN
3004
CALL Info('ListSetParameters',&
3005
'Scaled number of parameters: '//I2S(cnt),Level=6)
3006
ELSE
3007
CALL Warn('ListSetParameters','No parameters were altered!')
3008
END IF
3009
3010
CONTAINS
3011
3012
SUBROUTINE ListSetTagged(list, partag, val, mult, cnt)
3013
TYPE(ValueList_t), POINTER :: list
3014
INTEGER :: partag
3015
REAL(KIND=dp) :: val
3016
LOGICAL :: mult
3017
INTEGER :: cnt
3018
3019
TYPE(ValueListEntry_t), POINTER :: ptr
3020
3021
IF(.NOT.ASSOCIATED(List)) RETURN
3022
3023
ptr => List % Head
3024
DO WHILE( ASSOCIATED(ptr) )
3025
IF( partag == 0 ) THEN
3026
IF( ptr % disttag ) THEN
3027
IF(ASSOCIATED(Weights)) THEN
3028
IF( Weights(i) > TINY(Weights(i)) ) THEN
3029
ptr % coeff = 1.0_dp / Weights(i)
3030
cnt = cnt + 1
3031
WRITE( Message,'(A,ES12.3)') 'Scaling parameter "'//TRIM(ptr % name)//'" with:',ptr % coeff
3032
CALL Info('ListSetParameters',Message,Level=15)
3033
ELSE
3034
CALL Warn('ListSetParameters','Refusing division with zero!')
3035
END IF
3036
END IF
3037
END IF
3038
ELSE IF(partag == ptr % partag ) THEN
3039
IF( mult ) THEN
3040
ptr % coeff = val * ptr % coeff
3041
ELSE
3042
ptr % coeff = val
3043
END IF
3044
cnt = cnt + 1
3045
END IF
3046
ptr => ptr % Next
3047
END DO
3048
END SUBROUTINE ListSetTagged
3049
3050
END SUBROUTINE ListSetParameters
3051
!-----------------------------------------------------------------------------------
3052
3053
3054
!----------------------------------------------------------------
3055
!> Echo parameters for debugging purposes.
3056
!> For now only supports constants...
3057
!----------------------------------------------------------------
3058
SUBROUTINE ListEchoKeywords( Model )
3059
!----------------------------------------------------------------
3060
TYPE(Model_t) :: Model
3061
!----------------------------------------------------------------
3062
INTEGER :: i,cnt
3063
3064
CALL Info('ListEchoKeywords','Echoing parameters for debgging purposes')
3065
3066
CALL EchoList(Model % Simulation, 0, 'simulation' )
3067
CALL EchoList(Model % Constants, 0, 'constants' )
3068
DO i=1,Model % NumberOfEquations
3069
CALL EchoList(Model % Equations(i) % Values, i, 'equation' )
3070
END DO
3071
DO i=1,Model % NumberOfBodies
3072
CALL EchoList(Model % Bodies(i) % Values, i, 'body' )
3073
END DO
3074
DO i=1,Model % NumberOfBoundaries
3075
CALL EchoList(Model % Boundaries(i) % Values, i, 'boundary' )
3076
END DO
3077
DO i=1,Model % NumberOfBodyForces
3078
CALL EchoList(Model % BodyForces(i) % Values, i, 'body force' )
3079
END DO
3080
DO i=1,Model % NumberOfBCs
3081
CALL EchoList(Model % BCs(i) % Values, i, 'boundary condition' )
3082
END DO
3083
DO i=1,Model % NumberOfMaterials
3084
CALL EchoList(Model % Materials(i) % Values, i, 'material' )
3085
END DO
3086
DO i=1,Model % NumberOfComponents
3087
CALL EchoList(Model % Components(i) % Values, i, 'component' )
3088
END DO
3089
DO i=1,Model % NumberOfICs
3090
CALL EchoList(Model % ICs(i) % Values, i, 'initial condition' )
3091
END DO
3092
DO i=1,Model % NumberOfSolvers
3093
CALL EchoList(Model % Solvers(i) % Values, i, 'solver ' )
3094
END DO
3095
3096
CONTAINS
3097
3098
SUBROUTINE EchoList(list, i, section )
3099
TYPE(ValueList_t), POINTER :: list
3100
INTEGER :: i
3101
CHARACTER(LEN=*) :: section
3102
CHARACTER(LEN=MAX_NAME_LEN) :: str
3103
3104
TYPE(ValueListEntry_t), POINTER :: ptr
3105
3106
IF(.NOT.ASSOCIATED(List)) RETURN
3107
3108
ptr => List % Head
3109
DO WHILE( ASSOCIATED(ptr) )
3110
SELECT CASE(ptr % TYPE)
3111
CASE( LIST_TYPE_CONSTANT_SCALAR )
3112
WRITE(str,'(A,ES12.3)') 'Real ',ptr % Coeff * ptr % Fvalues(1,1,1)
3113
3114
CASE( LIST_TYPE_LOGICAL )
3115
IF( ptr % LValue ) THEN
3116
str = 'Logical True'
3117
ELSE
3118
str = 'Logical False'
3119
END IF
3120
CASE( LIST_TYPE_INTEGER )
3121
str = 'Integer '//I2S(ptr % Ivalues(1))
3122
3123
CASE DEFAULT
3124
ptr => ptr % Next
3125
CYCLE
3126
END SELECT
3127
3128
IF( i==0 ) THEN
3129
WRITE(*,'(A)') TRIM(Section)//' :: '//TRIM(ptr % Name)//' '//TRIM(str)
3130
ELSE
3131
WRITE(*,'(A)') TRIM(Section)//' '//I2S(i)//' :: '//TRIM(ptr % name)//' '//TRIM(str)
3132
END IF
3133
ptr => ptr % Next
3134
END DO
3135
3136
END SUBROUTINE EchoList
3137
3138
END SUBROUTINE ListEchoKeywords
3139
!-----------------------------------------------------------------------------------
3140
3141
3142
!-----------------------------------------------------------------------------------
3143
!> Copies an entry from 'ptr' to an entry in *different* list with the same content.
3144
!-----------------------------------------------------------------------------------
3145
SUBROUTINE ListCopyItem( ptr, list, name )
3146
3147
TYPE(ValueListEntry_t), POINTER :: ptr
3148
TYPE(ValueList_t), POINTER :: list
3149
CHARACTER(LEN=*), OPTIONAL :: name
3150
!------------------------------------------------------------------------------
3151
INTEGER :: i,j,k
3152
TYPE(ValueListEntry_t), POINTER :: ptrb, ptrnext
3153
3154
IF( PRESENT( name ) ) THEN
3155
ptrb => ListAdd( List, Name )
3156
ELSE
3157
ptrb => ListAdd( List, ptr % Name )
3158
END IF
3159
3160
3161
ptrnext => ptrb % next
3162
ptrb = ptr
3163
3164
ptrb % tvalues => null()
3165
if(associated(ptr % tvalues)) then
3166
allocate( ptrb % tvalues(size(ptr % tvalues)) )
3167
ptrb % tvalues = ptr % tvalues
3168
end if
3169
3170
ptrb % fvalues => null()
3171
if(associated(ptr % fvalues)) then
3172
i = size(ptr % fvalues,1)
3173
j = size(ptr % fvalues,2)
3174
k = size(ptr % fvalues,3)
3175
allocate( ptrb % fvalues(i,j,k) )
3176
ptrb % fvalues = ptr % fvalues
3177
end if
3178
3179
ptrb % ivalues => null()
3180
if(associated(ptr % ivalues)) then
3181
allocate( ptrb % ivalues(size(ptr % ivalues)) )
3182
ptrb % ivalues = ptr % ivalues
3183
end if
3184
3185
ptrb % cumulative => null()
3186
if(associated(ptr % cumulative)) then
3187
allocate( ptrb % cumulative(size(ptr % cumulative)) )
3188
ptrb % cumulative = ptr % cumulative
3189
end if
3190
ptrb % next => ptrnext
3191
3192
! If name is given then we have to revert the stuff from previous lines
3193
IF( PRESENT( name ) ) THEN
3194
ptrb % Name = name
3195
ptrb % Namelen = lentrim( name )
3196
END IF
3197
3198
#ifdef DEVEL_LISTCOUNTER
3199
IF( ASSOCIATED( ptr ) ) THEN
3200
ptr % Counter = ptr % Counter + 1
3201
END IF
3202
#endif
3203
#ifdef DEVEL_LISTUSAGE
3204
IF( ASSOCIATED( ptr ) ) THEN
3205
ptr % Counter = 1
3206
END IF
3207
#endif
3208
3209
END SUBROUTINE ListCopyItem
3210
3211
3212
!> Checks two lists for a given keyword. If it is given then
3213
!> copy it as it is to the 2nd list.
3214
!------------------------------------------------------------------------------
3215
SUBROUTINE ListCompareAndCopy( list, listb, name, Found, remove, nooverwrite)
3216
!------------------------------------------------------------------------------
3217
TYPE(ValueList_t), POINTER :: list, listb
3218
CHARACTER(LEN=*) :: name
3219
LOGICAL, OPTIONAL :: Found
3220
LOGICAL, OPTIONAL :: remove
3221
LOGICAL, OPTIONAL :: nooverwrite
3222
!------------------------------------------------------------------------------
3223
TYPE(ValueListEntry_t), POINTER :: ptr
3224
CHARACTER(LEN=LEN_TRIM(Name)) :: str
3225
INTEGER :: k, n
3226
3227
k = StringToLowerCase( str,Name,.TRUE. )
3228
IF(PRESENT(Found)) Found = .FALSE.
3229
3230
IF(PRESENT(nooverwrite)) THEN
3231
IF(nooverwrite) THEN
3232
IF( ListCheckPresent( listb, str ) ) RETURN
3233
END IF
3234
END IF
3235
3236
! Find the keyword from the 1st list
3237
Ptr => List % Head
3238
DO WHILE( ASSOCIATED(ptr) )
3239
n = ptr % NameLen
3240
IF ( n==k ) THEN
3241
IF ( ptr % Name(1:n) == str(1:n) ) EXIT
3242
END IF
3243
ptr => ptr % Next
3244
END DO
3245
3246
IF(.NOT. ASSOCIATED( ptr ) ) RETURN
3247
3248
! Add the same entry to the 2nd list
3249
CALL ListCopyItem( ptr, listb )
3250
IF(PRESENT(Found)) Found = .TRUE.
3251
3252
IF( PRESENT(remove) ) THEN
3253
IF( remove ) CALL ListRemove( list, name)
3254
END IF
3255
3256
3257
END SUBROUTINE ListCompareAndCopy
3258
3259
3260
!> Goes through one list and checks whether it includes any keywords with give prefix.
3261
!> All keywords found are copied to the 2nd list without the prefix.
3262
!------------------------------------------------------------------------------
3263
SUBROUTINE ListCopyPrefixedKeywords( list, listb, prefix )
3264
!------------------------------------------------------------------------------
3265
TYPE(ValueList_t), POINTER :: list, listb
3266
CHARACTER(LEN=*) :: prefix
3267
!------------------------------------------------------------------------------
3268
TYPE(ValueListEntry_t), POINTER :: ptr
3269
CHARACTER(LEN=LEN_TRIM(prefix)) :: str
3270
INTEGER :: k, l, n, ncopy
3271
3272
k = StringToLowerCase( str,prefix,.TRUE. )
3273
ncopy = 0
3274
3275
! Find the keyword from the 1st list
3276
Ptr => List % Head
3277
DO WHILE( ASSOCIATED(ptr) )
3278
n = ptr % NameLen
3279
IF( n > k ) THEN
3280
IF( ptr % Name(1:k) == str(1:k) ) THEN
3281
l = k+1
3282
! Remove the extra blanco after prefix if present
3283
! Here we just assume one possible blanco as that is most often the case
3284
IF( ptr % Name(l:l) == ' ') l = l+1
3285
CALL Info('ListCopyPrefixedKeywords',&
3286
'Prefix: '//TRIM(prefix)// ' Keyword: '//TRIM(ptr % Name(l:n)),Level=12)
3287
CALL ListCopyItem( ptr, listb, ptr % Name(l:n) )
3288
ncopy = ncopy + 1
3289
END IF
3290
END IF
3291
ptr => ptr % Next
3292
END DO
3293
3294
IF( ncopy > 0 ) THEN
3295
CALL Info('ListCopyPrefixedKeywords',&
3296
'Copied '//I2S(ncopy)//' keywords with prefix: '//TRIM(prefix),Level=6)
3297
END IF
3298
3299
END SUBROUTINE ListCopyPrefixedKeywords
3300
3301
3302
!> Goes through one list and copies all keywords to a second list.
3303
!------------------------------------------------------------------------------
3304
SUBROUTINE ListCopyAllKeywords( list, listb )
3305
!------------------------------------------------------------------------------
3306
TYPE(ValueList_t), POINTER :: list, listb
3307
!------------------------------------------------------------------------------
3308
TYPE(ValueListEntry_t), POINTER :: ptr
3309
INTEGER :: ncopy
3310
3311
ncopy = 0
3312
3313
! Find the keyword from the 1st list
3314
Ptr => List % Head
3315
DO WHILE( ASSOCIATED(ptr) )
3316
CALL ListCopyItem( ptr, listb, ptr % Name )
3317
ncopy = ncopy + 1
3318
ptr => ptr % Next
3319
END DO
3320
3321
IF( ncopy > 0 ) THEN
3322
CALL Info('ListCopyAllKeywords',&
3323
'Copied '//I2S(ncopy)//' keywords to new list',Level=6)
3324
END IF
3325
3326
END SUBROUTINE ListCopyAllKeywords
3327
3328
3329
!------------------------------------------------------------------------------
3330
!> Check that obsolete keyword is not used instead of the new one.
3331
!------------------------------------------------------------------------------
3332
SUBROUTINE ListObsoleteWarn( List,OldName,NewName )
3333
!------------------------------------------------------------------------------
3334
TYPE(ValueList_t), POINTER :: List
3335
CHARACTER(LEN=*) :: OldName,NewName
3336
!------------------------------------------------------------------------------
3337
LOGICAL :: Found
3338
TYPE(ValueListEntry_t), POINTER :: ptr
3339
!------------------------------------------------------------------------------
3340
ptr => ListFind(List,OldName,Found)
3341
IF( Found ) THEN
3342
CALL Warn('ListFatalObsolete',&
3343
'Use keyword "'//TRIM(NewName)//'" instead of "'//TRIM(OldName)//'"')
3344
END IF
3345
!------------------------------------------------------------------------------
3346
END SUBROUTINE ListObsoleteWarn
3347
!------------------------------------------------------------------------------
3348
3349
!------------------------------------------------------------------------------
3350
!> Check that obsolete keyword is not used instead of the new one.
3351
!------------------------------------------------------------------------------
3352
SUBROUTINE ListObsoleteFatal( List,OldName,NewName )
3353
!------------------------------------------------------------------------------
3354
TYPE(ValueList_t), POINTER :: List
3355
CHARACTER(LEN=*) :: OldName,NewName
3356
!------------------------------------------------------------------------------
3357
LOGICAL :: Found
3358
TYPE(ValueListEntry_t), POINTER :: ptr
3359
!------------------------------------------------------------------------------
3360
ptr => ListFind(List,OldName,Found)
3361
IF( Found ) THEN
3362
CALL Fatal('ListFatalObsolete',&
3363
'Use keyword "'//TRIM(NewName)//'" instead of "'//TRIM(OldName)//'"')
3364
END IF
3365
!------------------------------------------------------------------------------
3366
END SUBROUTINE ListObsoleteFatal
3367
!------------------------------------------------------------------------------
3368
3369
3370
3371
!------------------------------------------------------------------------------
3372
!> Just checks if there is a untreated keyword in the routine in the list.
3373
!> In case there is return a warning.
3374
!------------------------------------------------------------------------------
3375
SUBROUTINE ListUntreatedWarn( List, Name, Caller )
3376
!------------------------------------------------------------------------------
3377
TYPE(ValueList_t), POINTER :: List
3378
CHARACTER(LEN=*) :: Name
3379
CHARACTER(LEN=*), OPTIONAL :: Caller
3380
!------------------------------------------------------------------------------
3381
IF( ListCheckPresent( List, Name ) ) THEN
3382
IF( PRESENT( Caller ) ) THEN
3383
CALL Warn(Caller,'Untreated keyword may cause problems: '//TRIM(Name))
3384
ELSE
3385
CALL Warn('ListUntreatedWarn','Untreated keyword may cause problems: '//TRIM(Name))
3386
END IF
3387
END IF
3388
!------------------------------------------------------------------------------
3389
END SUBROUTINE ListUntreatedWarn
3390
!------------------------------------------------------------------------------
3391
3392
!------------------------------------------------------------------------------
3393
!> Just checks if there is a untreated keyword in the routine in the list.
3394
!> In case there is return a Fatal.
3395
!------------------------------------------------------------------------------
3396
SUBROUTINE ListUntreatedFatal( List, Name, Caller )
3397
!------------------------------------------------------------------------------
3398
TYPE(ValueList_t), POINTER :: List
3399
CHARACTER(LEN=*) :: Name
3400
CHARACTER(LEN=*), OPTIONAL :: Caller
3401
!------------------------------------------------------------------------------
3402
IF( ListCheckPresent( List, Name ) ) THEN
3403
IF( PRESENT( Caller ) ) THEN
3404
CALL Fatal(Caller,'Untreated keyword: '//TRIM(Name))
3405
ELSE
3406
CALL Fatal('ListUntreatedFatal','Untreated keyword: '//TRIM(Name))
3407
END IF
3408
END IF
3409
!------------------------------------------------------------------------------
3410
END SUBROUTINE ListUntreatedFatal
3411
!------------------------------------------------------------------------------
3412
3413
!------------------------------------------------------------------------------
3414
!> Just checks if a prefix is present in the list.
3415
!------------------------------------------------------------------------------
3416
FUNCTION ListCheckPrefix( List,Name ) RESULT(Found)
3417
!------------------------------------------------------------------------------
3418
TYPE(ValueList_t), POINTER :: List
3419
CHARACTER(LEN=*) :: Name
3420
LOGICAL :: Found
3421
!------------------------------------------------------------------------------
3422
TYPE(ValueListEntry_t), POINTER :: ptr
3423
!------------------------------------------------------------------------------
3424
ptr => ListFindPrefix(List,Name,Found)
3425
!------------------------------------------------------------------------------
3426
END FUNCTION ListCheckPrefix
3427
!------------------------------------------------------------------------------
3428
3429
!------------------------------------------------------------------------------
3430
!> Check if the keyword is with the given prefix is present in any boundary condition.
3431
!------------------------------------------------------------------------------
3432
FUNCTION ListCheckPrefixAnyBC( Model, Name ) RESULT(Found)
3433
!------------------------------------------------------------------------------
3434
TYPE(Model_t) :: Model
3435
CHARACTER(LEN=*) :: Name
3436
LOGICAL :: Found
3437
INTEGER :: bc
3438
TYPE(ValuelistEntry_t), POINTER :: ptr
3439
3440
Found = .FALSE.
3441
DO bc = 1,Model % NumberOfBCs
3442
ptr => ListFindPrefix( Model % BCs(bc) % Values, Name, Found )
3443
IF( Found ) EXIT
3444
END DO
3445
!------------------------------------------------------------------------------
3446
END FUNCTION ListCheckPrefixAnyBC
3447
!------------------------------------------------------------------------------
3448
3449
!------------------------------------------------------------------------------
3450
!> Check if the keyword is with the given prefix is present in any body.
3451
!------------------------------------------------------------------------------
3452
FUNCTION ListCheckPrefixAnyBody( Model, Name ) RESULT(Found)
3453
!------------------------------------------------------------------------------
3454
TYPE(Model_t) :: Model
3455
CHARACTER(LEN=*) :: Name
3456
LOGICAL :: Found
3457
INTEGER :: body_id
3458
TYPE(ValuelistEntry_t), POINTER :: ptr
3459
3460
Found = .FALSE.
3461
DO body_id = 1,Model % NumberOfBodies
3462
ptr => ListFindPrefix( Model % Bodies(body_id) % Values, Name, Found )
3463
IF( Found ) EXIT
3464
END DO
3465
!------------------------------------------------------------------------------
3466
END FUNCTION ListCheckPrefixAnyBody
3467
!------------------------------------------------------------------------------
3468
3469
!------------------------------------------------------------------------------
3470
!> Check if the keyword is with the given prefix is present in any material.
3471
!------------------------------------------------------------------------------
3472
FUNCTION ListCheckPrefixAnyMaterial( Model, Name ) RESULT(Found)
3473
!------------------------------------------------------------------------------
3474
TYPE(Model_t) :: Model
3475
CHARACTER(LEN=*) :: Name
3476
LOGICAL :: Found
3477
INTEGER :: mat_id
3478
TYPE(ValuelistEntry_t), POINTER :: ptr
3479
3480
Found = .FALSE.
3481
DO mat_id = 1,Model % NumberOfMaterials
3482
ptr => ListFindPrefix( Model % Materials(mat_id) % Values, Name, Found )
3483
IF( Found ) EXIT
3484
END DO
3485
!------------------------------------------------------------------------------
3486
END FUNCTION ListCheckPrefixAnyMaterial
3487
!------------------------------------------------------------------------------
3488
3489
!------------------------------------------------------------------------------
3490
!> Check if the keyword is with the given prefix is present in any body force.
3491
!------------------------------------------------------------------------------
3492
FUNCTION ListCheckPrefixAnyBodyForce( Model, Name ) RESULT(Found)
3493
!------------------------------------------------------------------------------
3494
TYPE(Model_t) :: Model
3495
CHARACTER(LEN=*) :: Name
3496
LOGICAL :: Found
3497
INTEGER :: bf_id
3498
TYPE(ValuelistEntry_t), POINTER :: ptr
3499
3500
Found = .FALSE.
3501
DO bf_id = 1,Model % NumberOfBodyForces
3502
ptr => ListFindPrefix( Model % BodyForces(bf_id) % Values, Name, Found )
3503
IF( Found ) EXIT
3504
END DO
3505
!------------------------------------------------------------------------------
3506
END FUNCTION ListCheckPrefixAnyBodyForce
3507
!------------------------------------------------------------------------------
3508
3509
3510
3511
!------------------------------------------------------------------------------
3512
!> Adds a string to the list.
3513
!------------------------------------------------------------------------------
3514
SUBROUTINE ListAddString( List,Name,CValue,CaseConversion )
3515
!------------------------------------------------------------------------------
3516
TYPE(ValueList_t), POINTER :: List
3517
CHARACTER(LEN=*) :: Name
3518
CHARACTER(LEN=*) :: CValue
3519
LOGICAL, OPTIONAL :: CaseConversion
3520
!------------------------------------------------------------------------------
3521
INTEGER :: n
3522
LOGICAL :: DoCase
3523
TYPE(ValueListEntry_t), POINTER :: ptr
3524
!------------------------------------------------------------------------------
3525
ptr => ListAdd( List, Name )
3526
3527
DoCase = .TRUE.
3528
IF ( PRESENT(CaseConversion) ) DoCase = CaseConversion
3529
3530
n = LEN_TRIM(Cvalue)
3531
IF(ALLOCATED(ptr % Cvalue)) DEALLOCATE(ptr % Cvalue)
3532
ALLOCATE(CHARACTER(n)::ptr % Cvalue)
3533
IF ( DoCase ) THEN
3534
n = StringToLowerCase( ptr % CValue,CValue )
3535
ELSE
3536
n = MIN( MAX_NAME_LEN,LEN(CValue) )
3537
ptr % CValue = TRIM(Cvalue)
3538
END IF
3539
3540
ptr % TYPE = LIST_TYPE_STRING
3541
n = LEN_TRIM(Name)
3542
IF(ALLOCATED(ptr % Name)) DEALLOCATE(ptr % Name)
3543
ALLOCATE(CHARACTER(n)::ptr % Name)
3544
ptr % NameLen = StringToLowerCase( Ptr % Name,Name )
3545
!------------------------------------------------------------------------------
3546
END SUBROUTINE ListAddString
3547
!------------------------------------------------------------------------------
3548
3549
3550
!------------------------------------------------------------------------------
3551
!> Adds a logical entry to the list.
3552
!------------------------------------------------------------------------------
3553
SUBROUTINE ListAddLogical( List,Name,LValue )
3554
!------------------------------------------------------------------------------
3555
TYPE(ValueList_t), POINTER :: List
3556
CHARACTER(LEN=*) :: Name
3557
LOGICAL :: LValue
3558
!------------------------------------------------------------------------------
3559
INTEGER :: n
3560
TYPE(ValueListEntry_t), POINTER :: ptr
3561
!------------------------------------------------------------------------------
3562
ptr => ListAdd( List, Name )
3563
Ptr % LValue = LValue
3564
Ptr % TYPE = LIST_TYPE_LOGICAL
3565
3566
n = LEN_TRIM(Name)
3567
IF(ALLOCATED(ptr % Name)) DEALLOCATE(ptr % Name)
3568
ALLOCATE(CHARACTER(n)::ptr % Name)
3569
Ptr % NameLen = StringToLowerCase( ptr % Name,Name )
3570
END SUBROUTINE ListAddLogical
3571
!------------------------------------------------------------------------------
3572
3573
3574
!------------------------------------------------------------------------------
3575
!> Adds an address integer to the list.
3576
!------------------------------------------------------------------------------
3577
SUBROUTINE ListAddAddressInteger( List,Name,AValue )
3578
!------------------------------------------------------------------------------
3579
TYPE(ValueList_t), POINTER :: List
3580
CHARACTER(LEN=*) :: Name
3581
INTEGER(kind=AddrInt) :: AValue
3582
!------------------------------------------------------------------------------
3583
INTEGER :: n
3584
TYPE(ValueListEntry_t), POINTER :: ptr
3585
!------------------------------------------------------------------------------
3586
ptr => ListAdd( List, Name )
3587
ptr % PROCEDURE = Avalue
3588
3589
ptr % TYPE = LIST_TYPE_ADDRINT
3590
3591
n = LEN_TRIM(Name)
3592
IF(ALLOCATED(ptr % Name)) DEALLOCATE(ptr % Name)
3593
ALLOCATE(CHARACTER(n)::ptr % Name)
3594
ptr % NameLen = StringToLowerCase( ptr % Name,Name )
3595
END SUBROUTINE ListAddAddressInteger
3596
!------------------------------------------------------------------------------
3597
3598
!------------------------------------------------------------------------------
3599
!> Adds an integer to the list.
3600
!------------------------------------------------------------------------------
3601
SUBROUTINE ListAddInteger( List,Name,IValue,Proc )
3602
!------------------------------------------------------------------------------
3603
TYPE(ValueList_t), POINTER :: List
3604
CHARACTER(LEN=*) :: Name
3605
INTEGER :: IValue
3606
INTEGER(Kind=AddrInt), OPTIONAL :: Proc
3607
!------------------------------------------------------------------------------
3608
INTEGER :: n
3609
TYPE(ValueListEntry_t), POINTER :: ptr
3610
!------------------------------------------------------------------------------
3611
ptr => ListAdd( List, Name )
3612
IF ( PRESENT(Proc) ) ptr % PROCEDURE = Proc
3613
3614
ALLOCATE( ptr % IValues(1) )
3615
ptr % IValues(1) = IValue
3616
ptr % TYPE = LIST_TYPE_INTEGER
3617
3618
n = LEN_TRIM(Name)
3619
IF(ALLOCATED(ptr % Name)) DEALLOCATE(ptr % Name)
3620
ALLOCATE(CHARACTER(n)::ptr % Name)
3621
ptr % NameLen = StringToLowerCase( ptr % Name,Name )
3622
END SUBROUTINE ListAddInteger
3623
!------------------------------------------------------------------------------
3624
3625
3626
!------------------------------------------------------------------------------
3627
!> Adds an integer array to the list.
3628
!------------------------------------------------------------------------------
3629
SUBROUTINE ListAddIntegerArray( List,Name,Nv,IValues,Proc )
3630
!------------------------------------------------------------------------------
3631
TYPE(ValueList_t), POINTER :: List
3632
CHARACTER(LEN=*) :: Name
3633
INTEGER :: Nv
3634
INTEGER :: IValues(Nv)
3635
INTEGER(KIND=AddrInt), OPTIONAL :: Proc
3636
!------------------------------------------------------------------------------
3637
INTEGER :: n
3638
TYPE(ValueListEntry_t), POINTER :: ptr
3639
!------------------------------------------------------------------------------
3640
ptr => ListAdd( List, Name )
3641
3642
ALLOCATE( ptr % IValues(Nv) )
3643
3644
IF ( PRESENT(Proc) ) ptr % PROCEDURE = Proc
3645
3646
ptr % TYPE = LIST_TYPE_INTEGER
3647
ptr % IValues(1:nv) = IValues(1:nv)
3648
3649
n = LEN_TRIM(Name)
3650
IF(ALLOCATED(ptr % Name)) DEALLOCATE(ptr % Name)
3651
ALLOCATE(CHARACTER(n)::ptr % Name)
3652
ptr % NameLen = StringToLowerCase( ptr % Name,Name )
3653
END SUBROUTINE ListAddIntegerArray
3654
!------------------------------------------------------------------------------
3655
3656
!------------------------------------------------------------------------------
3657
!> Adds a constant real value to the list.
3658
!------------------------------------------------------------------------------
3659
SUBROUTINE ListAddConstReal( List,Name,FValue,Proc,CValue )
3660
!------------------------------------------------------------------------------
3661
TYPE(ValueList_t), POINTER :: List
3662
CHARACTER(LEN=*) :: Name
3663
CHARACTER(LEN=*), OPTIONAL :: Cvalue
3664
REAL(KIND=dp) :: FValue
3665
INTEGER(KIND=AddrInt), OPTIONAL :: Proc
3666
!------------------------------------------------------------------------------
3667
INTEGER :: n
3668
TYPE(ValueListEntry_t), POINTER :: ptr
3669
!------------------------------------------------------------------------------
3670
ptr => ListAdd( List, Name )
3671
3672
NULLIFY( ptr % TValues )
3673
ALLOCATE( ptr % FValues(1,1,1) )
3674
3675
ptr % FValues = FValue
3676
ptr % TYPE = LIST_TYPE_CONSTANT_SCALAR
3677
3678
IF ( PRESENT(Proc) ) THEN
3679
ptr % PROCEDURE = Proc
3680
IF( Proc /= 0 ) THEN
3681
ptr % TYPE = LIST_TYPE_CONSTANT_SCALAR_PROC
3682
END IF
3683
END IF
3684
3685
IF ( PRESENT( CValue ) ) THEN
3686
ptr % Cvalue = TRIM(CValue)
3687
ptr % TYPE = LIST_TYPE_CONSTANT_SCALAR_STR
3688
END IF
3689
3690
n = LEN_TRIM(Name)
3691
IF(ALLOCATED(ptr % Name)) DEALLOCATE(ptr % Name)
3692
ALLOCATE(CHARACTER(n)::ptr % Name)
3693
ptr % NameLen = StringToLowerCase( ptr % Name,Name )
3694
END SUBROUTINE ListAddConstReal
3695
!------------------------------------------------------------------------------
3696
3697
3698
!------------------------------------------------------------------------------
3699
!> Adds a linear dependency defined by a table of values, [x,y] to the list.
3700
!------------------------------------------------------------------------------
3701
SUBROUTINE ListAddDepReal(List,Name,DependName,N,TValues, &
3702
FValues,Proc,CValue,CubicTable, Monotone, Harmonic)
3703
!------------------------------------------------------------------------------
3704
TYPE(ValueList_t), POINTER :: List
3705
CHARACTER(LEN=*) :: Name,DependName
3706
CHARACTER(LEN=*), OPTIONAL :: Cvalue
3707
INTEGER :: N
3708
LOGICAL, OPTIONAL :: CubicTable, Monotone, Harmonic
3709
REAL(KIND=dp) :: FValues(N)
3710
REAL(KIND=dp) :: TValues(N)
3711
INTEGER(KIND=AddrInt), OPTIONAL :: Proc
3712
!------------------------------------------------------------------------------
3713
INTEGER :: l
3714
TYPE(ValueListEntry_t), POINTER :: ptr
3715
!------------------------------------------------------------------------------
3716
ptr => ListAdd( List, Name )
3717
IF ( PRESENT(Proc) ) ptr % PROCEDURE = Proc
3718
3719
ALLOCATE( ptr % FValues(1,1,n),ptr % TValues(n) )
3720
3721
! The (x,y) table should be such that values of x are increasing in size
3722
IF( .NOT. CheckMonotone( n, TValues ) ) THEN
3723
CALL Fatal('ListAddDepReal',&
3724
'Values x in > '//TRIM(Name)//' < not monotonically ordered!')
3725
END IF
3726
3727
ptr % TValues = TValues(1:n)
3728
ptr % FValues(1,1,:) = FValues(1:n)
3729
ptr % TYPE = LIST_TYPE_VARIABLE_SCALAR
3730
3731
IF(PRESENT(harmonic)) THEN
3732
IF(Harmonic) THEN
3733
CALL ConvertTableToHarmonic(n, ptr % TValues,ptr % Fvalues(1,1,:))
3734
END IF
3735
END IF
3736
3737
IF ( n>3 .AND. PRESENT(CubicTable)) THEN
3738
IF ( CubicTable ) THEN
3739
ALLOCATE(ptr % CubicCoeff(n))
3740
CALL CubicSpline(n,ptr % TValues,Ptr % Fvalues(1,1,:), &
3741
Ptr % CubicCoeff, Monotone )
3742
END IF
3743
END IF
3744
3745
ALLOCATE(ptr % Cumulative(n))
3746
CALL CumulativeIntegral(ptr % TValues, Ptr % FValues(1,1,:), &
3747
Ptr % CubicCoeff, Ptr % Cumulative )
3748
3749
l = LEN_TRIM(Name)
3750
IF(ALLOCATED(ptr % Name)) DEALLOCATE(ptr % Name)
3751
ALLOCATE(CHARACTER(l)::ptr % Name)
3752
ptr % NameLen = StringToLowerCase( ptr % Name,Name )
3753
3754
l = LEN_TRIM(DependName)
3755
IF(ALLOCATED(ptr % DependName)) DEALLOCATE(ptr % DependName)
3756
ALLOCATE(CHARACTER(l)::ptr % DependName)
3757
ptr % DepNameLen = StringToLowerCase( ptr % DependName,DependName )
3758
3759
IF ( PRESENT( Cvalue ) ) THEN
3760
ptr % CValue = CValue
3761
ptr % TYPE = LIST_TYPE_VARIABLE_SCALAR_STR
3762
END IF
3763
3764
END SUBROUTINE ListAddDepReal
3765
!------------------------------------------------------------------------------
3766
3767
3768
!------------------------------------------------------------------------------
3769
!> Adds a constant real valued array to the list.
3770
!------------------------------------------------------------------------------
3771
SUBROUTINE ListAddConstRealArray( List,Name,N,M,FValues,Proc,CValue )
3772
!------------------------------------------------------------------------------
3773
TYPE(ValueList_t), POINTER :: List
3774
CHARACTER(LEN=*) :: Name
3775
CHARACTER(LEN=*), OPTIONAL :: Cvalue
3776
INTEGER :: N,M
3777
REAL(KIND=dp) :: FValues(:,:)
3778
INTEGER(KIND=AddrInt), OPTIONAL :: Proc
3779
!------------------------------------------------------------------------------
3780
INTEGER :: l
3781
TYPE(ValueListEntry_t), POINTER :: ptr
3782
!------------------------------------------------------------------------------
3783
ptr => ListAdd( List, Name )
3784
3785
NULLIFY( ptr % TValues )
3786
ALLOCATE( ptr % FValues(N,M,1) )
3787
3788
ptr % Fdim = 0
3789
IF( N > 1 ) ptr % Fdim = 1
3790
IF( M > 1 ) ptr % Fdim = ptr % Fdim + 1
3791
3792
IF( ptr % Fdim == 0 ) THEN
3793
ptr % TYPE = LIST_TYPE_CONSTANT_SCALAR
3794
ELSE
3795
ptr % TYPE = LIST_TYPE_CONSTANT_TENSOR
3796
END IF
3797
ptr % FValues(1:n,1:m,1) = FValues(1:n,1:m)
3798
3799
IF ( PRESENT(Proc) ) THEN
3800
ptr % PROCEDURE = Proc
3801
END IF
3802
3803
IF ( PRESENT( Cvalue ) ) THEN
3804
ptr % CValue = CValue
3805
IF( ptr % Fdim == 0 ) THEN
3806
ptr % TYPE = LIST_TYPE_CONSTANT_SCALAR_STR
3807
ELSE
3808
ptr % TYPE = LIST_TYPE_CONSTANT_TENSOR_STR
3809
END IF
3810
END IF
3811
3812
l = LEN_TRIM(Name)
3813
IF(ALLOCATED(ptr % Name)) DEALLOCATE(ptr % Name)
3814
ALLOCATE(CHARACTER(l)::ptr % Name)
3815
ptr % NameLen = StringToLowerCase( ptr % Name,Name )
3816
END SUBROUTINE ListAddConstRealArray
3817
!------------------------------------------------------------------------------
3818
3819
3820
!------------------------------------------------------------------------------
3821
!> Adds a real array where the components are linearly dependent.
3822
!------------------------------------------------------------------------------
3823
SUBROUTINE ListAddDepRealArray(List,Name,DependName, &
3824
ni,TValues,n,m,FValues,Proc,Cvalue)
3825
!------------------------------------------------------------------------------
3826
TYPE(ValueList_t), POINTER :: List
3827
CHARACTER(LEN=*) :: Name,DependName
3828
CHARACTER(LEN=*), OPTIONAL :: Cvalue
3829
INTEGER :: ni,n,m
3830
REAL(KIND=dp) :: FValues(:,:,:)
3831
REAL(KIND=dp) :: TValues(ni)
3832
INTEGER(KIND=AddrInt), OPTIONAL :: Proc
3833
!------------------------------------------------------------------------------
3834
INTEGER :: l
3835
TYPE(ValueListEntry_t), POINTER :: ptr
3836
!------------------------------------------------------------------------------
3837
3838
ptr => ListAdd( List, Name )
3839
IF ( PRESENT(Proc) ) ptr % PROCEDURE = Proc
3840
3841
ALLOCATE( ptr % FValues(n,m,ni),ptr % TValues(ni) )
3842
3843
ptr % TValues = TValues(1:ni)
3844
ptr % FValues = FValues(1:n,1:m,1:ni)
3845
ptr % TYPE = LIST_TYPE_VARIABLE_TENSOR
3846
3847
ptr % fdim = 0
3848
IF( n > 1 ) ptr % fdim = 1
3849
IF( m > 1 ) ptr % fdim = ptr % fdim + 1
3850
3851
IF ( PRESENT( Cvalue ) ) THEN
3852
ptr % CValue = CValue
3853
ptr % TYPE = LIST_TYPE_VARIABLE_TENSOR_STR
3854
END IF
3855
3856
l = LEN_TRIM(Name)
3857
IF(ALLOCATED(ptr % Name)) DEALLOCATE(ptr % Name)
3858
ALLOCATE(CHARACTER(l)::ptr % Name)
3859
ptr % NameLen = StringToLowerCase( ptr % Name,Name )
3860
3861
l = LEN_TRIM(DependName)
3862
IF(ALLOCATED(ptr % DependName)) DEALLOCATE(ptr % DependName)
3863
ALLOCATE(CHARACTER(l)::ptr % DependName)
3864
ptr % DepNameLen = StringToLowerCase( ptr % DependName,DependName )
3865
!------------------------------------------------------------------------------
3866
END SUBROUTINE ListAddDepRealArray
3867
!------------------------------------------------------------------------------
3868
3869
3870
!------------------------------------------------------------------------------
3871
! Given real array transform it to dependence array. This can only be done
3872
! if the size of the array is suitable.
3873
!------------------------------------------------------------------------------
3874
SUBROUTINE ListRealArrayToDepReal(List,Name,DepName,CubicTable,Monotone)
3875
TYPE(ValueList_t), POINTER :: List
3876
CHARACTER(LEN=*) :: Name
3877
CHARACTER(LEN=*) :: DepName
3878
LOGICAL, OPTIONAL :: CubicTable, Monotone
3879
3880
TYPE(ValueListEntry_t), POINTER :: ptr
3881
INTEGER :: n,m, l
3882
REAL(KIND=dp), ALLOCATABLE :: TmpValues(:,:,:)
3883
3884
ptr => ListFind( List, Name )
3885
3886
! Change only constant real array!
3887
IF( ptr % TYPE /= LIST_TYPE_CONSTANT_TENSOR ) RETURN
3888
3889
IF(.NOT. ASSOCIATED(ptr) ) THEN
3890
CALL Warn('ListRealArrayToDepArray','Could not find: '//TRIM(Name))
3891
RETURN
3892
END IF
3893
3894
IF( ptr % Fdim < 2 ) THEN
3895
CALL Warn('ListRealArrayToDepArray','No array form to transform!')
3896
RETURN
3897
END IF
3898
3899
n = SIZE(ptr % FValues,1)
3900
m = SIZE(ptr % FValues,2)
3901
3902
IF( m /= 2 ) THEN
3903
CALL Warn('ListRealArrayToDepArray','Number of columns must be 2!')
3904
RETURN
3905
END IF
3906
3907
ALLOCATE( TmpValues(n,m,1) )
3908
TmpValues = ptr % FValues
3909
DEALLOCATE( ptr % FValues )
3910
3911
ALLOCATE( ptr % FValues(1,1,n), ptr % TValues(n) )
3912
ptr % FValues(1,1,1:n) = TmpValues(1:n,2,1)
3913
ptr % TValues(1:n) = TmpValues(1:n,1,1)
3914
DEALLOCATE( TmpValues )
3915
3916
! The (x,y) table should be such that values of x are increasing in size
3917
IF( .NOT. CheckMonotone( n, ptr % FValues(1,1,:) ) ) THEN
3918
CALL Fatal('ListRealArrayToDepReal',&
3919
'Values x in > '//TRIM(Name)//' < not monotonically ordered!')
3920
END IF
3921
3922
! Make it cubic if asked
3923
IF ( n>3 .AND. PRESENT(CubicTable)) THEN
3924
IF ( CubicTable ) THEN
3925
ALLOCATE(ptr % CubicCoeff(n))
3926
CALL CubicSpline(n,ptr % TValues,Ptr % Fvalues(1,1,:), &
3927
Ptr % CubicCoeff, Monotone )
3928
END IF
3929
END IF
3930
3931
ALLOCATE(ptr % Cumulative(n))
3932
CALL CumulativeIntegral(ptr % TValues, Ptr % FValues(1,1,:), &
3933
Ptr % CubicCoeff, Ptr % Cumulative )
3934
3935
! Copy the depname
3936
l = LEN_TRIM(DepName)
3937
IF(ALLOCATED(ptr % DependName)) DEALLOCATE(ptr % DependName)
3938
ALLOCATE(CHARACTER(l)::ptr % DependName)
3939
ptr % DepNameLen = StringToLowerCase( ptr % DependName,DepName )
3940
3941
! Finally, change the type
3942
ptr % TYPE = LIST_TYPE_VARIABLE_SCALAR
3943
3944
CALL Info('ListRealArrayToDepReal',&
3945
'Changed constant array to dependence table of size '//I2S(n)//'!')
3946
3947
END SUBROUTINE ListRealArrayToDepReal
3948
3949
3950
3951
!------------------------------------------------------------------------------
3952
!> Adds a logical entry to the list if it does not exist previously.
3953
!------------------------------------------------------------------------------
3954
SUBROUTINE ListAddNewLogical( List,Name,LValue )
3955
!------------------------------------------------------------------------------
3956
TYPE(ValueList_t), POINTER :: List
3957
CHARACTER(LEN=*) :: Name
3958
LOGICAL :: LValue
3959
!------------------------------------------------------------------------------
3960
TYPE(ValueListEntry_t), POINTER :: ptr
3961
!------------------------------------------------------------------------------
3962
IF( ListCheckPresent( List, Name ) ) RETURN
3963
3964
CALL ListAddLogical( List,Name,LValue )
3965
3966
END SUBROUTINE ListAddNewLogical
3967
!------------------------------------------------------------------------------
3968
3969
3970
!------------------------------------------------------------------------------
3971
!> Adds an integer to the list when not present previously.
3972
!------------------------------------------------------------------------------
3973
SUBROUTINE ListAddNewInteger( List,Name,IValue,Proc )
3974
!------------------------------------------------------------------------------
3975
TYPE(ValueList_t), POINTER :: List
3976
CHARACTER(LEN=*) :: Name
3977
INTEGER :: IValue
3978
INTEGER(Kind=AddrInt), OPTIONAL :: Proc
3979
!------------------------------------------------------------------------------
3980
TYPE(ValueListEntry_t), POINTER :: ptr
3981
!------------------------------------------------------------------------------
3982
IF( ListCheckPresent( List, Name ) ) RETURN
3983
3984
CALL ListAddInteger( List,Name,IValue,Proc )
3985
3986
END SUBROUTINE ListAddNewInteger
3987
!------------------------------------------------------------------------------
3988
3989
3990
!------------------------------------------------------------------------------
3991
!> Adds a constant real value to the list if not present.
3992
!------------------------------------------------------------------------------
3993
SUBROUTINE ListAddNewConstReal( List,Name,FValue,Proc,CValue )
3994
!------------------------------------------------------------------------------
3995
TYPE(ValueList_t), POINTER :: List
3996
CHARACTER(LEN=*) :: Name
3997
CHARACTER(LEN=*), OPTIONAL :: Cvalue
3998
REAL(KIND=dp) :: FValue
3999
INTEGER(KIND=AddrInt), OPTIONAL :: Proc
4000
!------------------------------------------------------------------------------
4001
TYPE(ValueListEntry_t), POINTER :: ptr
4002
!------------------------------------------------------------------------------
4003
IF( ListCheckPresent( List, Name ) ) RETURN
4004
4005
CALL ListAddConstReal( List,Name,FValue,Proc,CValue )
4006
4007
END SUBROUTINE ListAddNewConstReal
4008
!------------------------------------------------------------------------------
4009
4010
4011
4012
!------------------------------------------------------------------------------
4013
!> Add a string value to the list if not present.
4014
!------------------------------------------------------------------------------
4015
SUBROUTINE ListAddNewString( List,Name,CValue,CaseConversion )
4016
!------------------------------------------------------------------------------
4017
TYPE(ValueList_t), POINTER :: List
4018
CHARACTER(LEN=*) :: Name
4019
CHARACTER(LEN=*) :: CValue
4020
LOGICAL, OPTIONAL :: CaseConversion
4021
4022
IF( ListCheckPresent( List, Name ) ) RETURN
4023
4024
CALL ListAddString( List,Name,CValue,CaseConversion )
4025
4026
END SUBROUTINE ListAddNewString
4027
!------------------------------------------------------------------------------
4028
4029
!------------------------------------------------------------------------------
4030
!> Gets an address integer value from the list.
4031
!------------------------------------------------------------------------------
4032
RECURSIVE FUNCTION ListGetAddressInteger( List,Name,Found,UnfoundFatal,DefValue) RESULT(L)
4033
!------------------------------------------------------------------------------
4034
TYPE(ValueList_t), POINTER :: List
4035
CHARACTER(LEN=*) :: Name
4036
INTEGER(KIND=AddrInt), OPTIONAL :: DefValue
4037
INTEGER(KIND=AddrInt) :: L
4038
LOGICAL, OPTIONAL :: Found, UnfoundFatal
4039
!------------------------------------------------------------------------------
4040
TYPE(ValueListEntry_t), POINTER :: ptr
4041
!------------------------------------------------------------------------------
4042
IF(PRESENT(DefValue)) THEN
4043
L = DefValue
4044
ELSE
4045
L = 0
4046
END IF
4047
4048
ptr => ListFind(List,Name,Found)
4049
IF (.NOT.ASSOCIATED(ptr) ) THEN
4050
IF(PRESENT(UnfoundFatal)) THEN
4051
IF(UnfoundFatal) THEN
4052
WRITE(Message, '(A,A)') "Failed to find integer: ",Name
4053
CALL Fatal("ListGetInteger", Message)
4054
END IF
4055
END IF
4056
RETURN
4057
END IF
4058
4059
IF( ptr % type /= LIST_TYPE_ADDRINT ) THEN
4060
CALL Fatal('ListGetInteger','Invalid list type for: '//TRIM(Name))
4061
END IF
4062
4063
L = ptr % PROCEDURE
4064
4065
!------------------------------------------------------------------------------
4066
END FUNCTION ListGetAddressInteger
4067
!------------------------------------------------------------------------------
4068
4069
!------------------------------------------------------------------------------
4070
!> Gets a integer value from the list.
4071
!------------------------------------------------------------------------------
4072
RECURSIVE FUNCTION ListGetInteger( List,Name,Found,minv,maxv,UnfoundFatal,DefValue) RESULT(L)
4073
!------------------------------------------------------------------------------
4074
TYPE(ValueList_t), POINTER :: List
4075
CHARACTER(LEN=*) :: Name
4076
INTEGER, OPTIONAL :: DefValue
4077
INTEGER :: L
4078
LOGICAL, OPTIONAL :: Found, UnfoundFatal
4079
INTEGER, OPTIONAL :: minv,maxv
4080
!------------------------------------------------------------------------------
4081
TYPE(ValueListEntry_t), POINTER :: ptr
4082
!------------------------------------------------------------------------------
4083
IF(PRESENT(DefValue)) THEN
4084
L = DefValue
4085
ELSE
4086
L = 0
4087
END IF
4088
4089
ptr => ListFind(List,Name,Found)
4090
IF (.NOT.ASSOCIATED(ptr) ) THEN
4091
IF(PRESENT(UnfoundFatal)) THEN
4092
IF(UnfoundFatal) THEN
4093
WRITE(Message, '(A,A)') "Failed to find integer: ",Name
4094
CALL Fatal("ListGetInteger", Message)
4095
END IF
4096
END IF
4097
RETURN
4098
END IF
4099
4100
IF( ptr % type /= LIST_TYPE_INTEGER ) THEN
4101
CALL Fatal('ListGetInteger','Invalid list type for: '//TRIM(Name))
4102
END IF
4103
4104
IF ( ptr % PROCEDURE /= 0 ) THEN
4105
CALL ListPushActiveName(Name)
4106
L = ExecIntFunction( ptr % PROCEDURE, CurrentModel )
4107
CALL ListPopActiveName()
4108
ELSE
4109
IF ( .NOT. ASSOCIATED(ptr % IValues) ) THEN
4110
CALL Fatal( 'ListGetInteger', 'Value type for property ['//TRIM(Name)//&
4111
'] not used consistently.')
4112
END IF
4113
4114
L = ptr % IValues(1)
4115
END IF
4116
4117
IF ( PRESENT( minv ) ) THEN
4118
IF ( L < minv ) THEN
4119
WRITE( Message, '(A,I0,A,I0)') 'Given value ',L,' for property: ['//TRIM(Name)//&
4120
'] smaller than given minimum: ', minv
4121
CALL Fatal( 'ListGetInteger', Message )
4122
END IF
4123
END IF
4124
4125
IF ( PRESENT( maxv ) ) THEN
4126
IF ( L > maxv ) THEN
4127
WRITE( Message, '(A,I0,A,I0)') 'Given value ',L,' for property: ['//TRIM(Name)//&
4128
'] larger than given maximum: ', maxv
4129
CALL Fatal( 'ListGetInteger', Message )
4130
END IF
4131
END IF
4132
!------------------------------------------------------------------------------
4133
END FUNCTION ListGetInteger
4134
!------------------------------------------------------------------------------
4135
4136
4137
!------------------------------------------------------------------------------
4138
!> Gets a integer array from the list.
4139
!------------------------------------------------------------------------------
4140
RECURSIVE FUNCTION ListGetIntegerArray( List,Name,Found,UnfoundFatal ) RESULT( IValues )
4141
!------------------------------------------------------------------------------
4142
TYPE(ValueList_t), POINTER :: List
4143
CHARACTER(LEN=*) :: Name
4144
LOGICAL, OPTIONAL :: Found, UnfoundFatal
4145
!------------------------------------------------------------------------------
4146
TYPE(ValueListEntry_t), POINTER :: ptr
4147
INTEGER :: i,n
4148
INTEGER, POINTER :: IValues(:)
4149
!------------------------------------------------------------------------------
4150
NULLIFY( IValues )
4151
ptr => ListFind(List,Name,Found)
4152
IF (.NOT.ASSOCIATED(ptr) ) THEN
4153
IF(PRESENT(UnfoundFatal)) THEN
4154
IF(UnfoundFatal) THEN
4155
WRITE(Message, '(A,A)') "Failed to find integer array: ",Name
4156
CALL Fatal("ListGetIntegerArray", Message)
4157
END IF
4158
END IF
4159
RETURN
4160
END IF
4161
4162
IF ( .NOT. ASSOCIATED(ptr % IValues) ) THEN
4163
CALL Fatal( 'ListGetIntegerArray', 'Value type for property ['//TRIM(Name)//&
4164
'] not used consistently.')
4165
END IF
4166
4167
n = SIZE(ptr % IValues)
4168
IValues => Ptr % IValues(1:n)
4169
4170
IF ( ptr % PROCEDURE /= 0 ) THEN
4171
CALL ListPushActiveName(Name)
4172
IValues = 0
4173
DO i=1,N
4174
Ivalues(i) = ExecIntFunction( ptr % PROCEDURE, CurrentModel )
4175
END DO
4176
CALL ListPopActiveName()
4177
END IF
4178
!------------------------------------------------------------------------------
4179
END FUNCTION ListGetIntegerArray
4180
!------------------------------------------------------------------------------
4181
4182
4183
!------------------------------------------------------------------------------
4184
!> Check whether the keyword is associated to an integer or real array.
4185
!------------------------------------------------------------------------------
4186
RECURSIVE FUNCTION ListCheckIsArray( List,Name,Found ) RESULT( IsArray )
4187
!------------------------------------------------------------------------------
4188
TYPE(ValueList_t), POINTER :: List
4189
CHARACTER(LEN=*) :: Name
4190
LOGICAL, OPTIONAL :: Found
4191
LOGICAL :: IsArray
4192
!------------------------------------------------------------------------------
4193
TYPE(ValueListEntry_t), POINTER :: ptr
4194
INTEGER :: n
4195
!------------------------------------------------------------------------------
4196
4197
ptr => ListFind(List,Name,Found)
4198
IsArray = .FALSE.
4199
IF(.NOT. ASSOCIATED( ptr ) ) RETURN
4200
4201
n = 0
4202
IF ( ASSOCIATED(ptr % IValues) ) THEN
4203
n = SIZE(ptr % IValues)
4204
END IF
4205
IF( ASSOCIATED( ptr % FValues ) ) THEN
4206
n = SIZE(ptr % FValues)
4207
END IF
4208
4209
IsArray = ( n > 1 )
4210
4211
!------------------------------------------------------------------------------
4212
END FUNCTION ListCheckIsArray
4213
!------------------------------------------------------------------------------
4214
4215
4216
4217
!------------------------------------------------------------------------------
4218
!> Gets a logical value from the list, if not found return False.
4219
!------------------------------------------------------------------------------
4220
RECURSIVE FUNCTION ListGetLogical( List,Name,Found,UnfoundFatal,DefValue ) RESULT(L)
4221
!------------------------------------------------------------------------------
4222
TYPE(ValueList_t), POINTER :: List
4223
CHARACTER(LEN=*) :: Name
4224
LOGICAL :: L
4225
LOGICAL, OPTIONAL :: Found, UnfoundFatal, DefValue
4226
!------------------------------------------------------------------------------
4227
TYPE(ValueListEntry_t), POINTER :: ptr
4228
!------------------------------------------------------------------------------
4229
IF(PRESENT(DefValue)) THEN
4230
L = DefValue
4231
ELSE
4232
L = .FALSE.
4233
END IF
4234
4235
ptr => ListFind(List,Name,Found)
4236
IF (.NOT.ASSOCIATED(ptr) ) THEN
4237
IF(PRESENT(UnfoundFatal)) THEN
4238
IF(UnfoundFatal) THEN
4239
WRITE(Message, '(A,A)') "Failed to find logical: ",Name
4240
CALL Fatal("ListGetLogical", Message)
4241
END IF
4242
END IF
4243
RETURN
4244
END IF
4245
4246
IF(ptr % TYPE == LIST_TYPE_LOGICAL ) THEN
4247
L = ptr % Lvalue
4248
ELSE
4249
CALL Fatal('ListGetLogical','Invalid list type for: '//TRIM(Name))
4250
END IF
4251
4252
!------------------------------------------------------------------------------
4253
END FUNCTION ListGetLogical
4254
!------------------------------------------------------------------------------
4255
4256
4257
4258
!------------------------------------------------------------------------------
4259
!> A generalized version of ListGetLogical. Uses logical, only if the keyword is
4260
!> of type locical, if the type is real it return True for positive values,
4261
!> and otherwise returns True IF the keyword is present.
4262
!> Since the absence if a sign of False there is no separate Found flag.
4263
!------------------------------------------------------------------------------
4264
RECURSIVE FUNCTION ListGetLogicalGen( List, Name) RESULT(L)
4265
!------------------------------------------------------------------------------
4266
TYPE(ValueList_t), POINTER :: List
4267
CHARACTER(LEN=*) :: Name
4268
LOGICAL :: L
4269
!------------------------------------------------------------------------------
4270
TYPE(ValueListEntry_t), POINTER :: ptr
4271
LOGICAL :: Found
4272
REAL(KIND=dp) :: Rval
4273
!------------------------------------------------------------------------------
4274
4275
L = .FALSE.
4276
4277
ptr => ListFind(List,Name,Found)
4278
IF ( .NOT. ASSOCIATED(ptr) ) RETURN
4279
4280
IF(ptr % TYPE == LIST_TYPE_LOGICAL ) THEN
4281
L = ptr % Lvalue
4282
4283
ELSE IF ( ptr % TYPE == LIST_TYPE_CONSTANT_SCALAR .OR. &
4284
ptr % TYPE == LIST_TYPE_CONSTANT_SCALAR_STR .OR. &
4285
ptr % TYPE == LIST_TYPE_CONSTANT_SCALAR_PROC ) THEN
4286
4287
RVal = ListGetConstReal( List, Name )
4288
L = ( RVal > 0.0_dp )
4289
ELSE
4290
L = .TRUE.
4291
!Mere presence implies true mask
4292
!CALL Fatal('ListGetLogicalGen','Invalid list type for: '//TRIM(Name))
4293
END IF
4294
4295
!------------------------------------------------------------------------------
4296
END FUNCTION ListGetLogicalGen
4297
!------------------------------------------------------------------------------
4298
4299
4300
4301
!------------------------------------------------------------------------------
4302
!> Gets a string from the list by its name, if not found return empty string.
4303
!------------------------------------------------------------------------------
4304
RECURSIVE FUNCTION ListGetString( List,Name,Found,UnfoundFatal,DefValue ) RESULT(S)
4305
!------------------------------------------------------------------------------
4306
TYPE(ValueList_t), POINTER :: List
4307
CHARACTER(LEN=*) :: Name
4308
LOGICAL, OPTIONAL :: Found,UnfoundFatal
4309
CHARACTER(:), ALLOCATABLE :: S
4310
CHARACTER(*), OPTIONAL :: DefValue
4311
!------------------------------------------------------------------------------
4312
TYPE(ValueListEntry_t), POINTER :: ptr
4313
!------------------------------------------------------------------------------
4314
S = ' '
4315
IF(PRESENT(DefValue)) S = TRIM(DefValue)
4316
4317
ptr => ListFind(List,Name,Found)
4318
IF (.NOT.ASSOCIATED(ptr) ) THEN
4319
IF(PRESENT(UnfoundFatal)) THEN
4320
IF(UnfoundFatal) THEN
4321
WRITE(Message, '(A,A)') "Failed to find string: ",Name
4322
CALL Fatal("ListGetString", Message)
4323
END IF
4324
END IF
4325
RETURN
4326
END IF
4327
4328
IF( ptr % Type == LIST_TYPE_STRING ) THEN
4329
S = TRIM(ptr % Cvalue)
4330
ELSE
4331
CALL Fatal('ListGetString','Invalid list type: '//TRIM(Name))
4332
END IF
4333
!------------------------------------------------------------------------------
4334
END FUNCTION ListGetString
4335
!------------------------------------------------------------------------------
4336
4337
!------------------------------------------------------------------------------
4338
!> Get a constant real from the list by its name.
4339
!------------------------------------------------------------------------------
4340
RECURSIVE FUNCTION ListGetConstReal( List,Name,Found,x,y,z,minv,maxv,UnfoundFatal,DefValue) RESULT(F)
4341
!------------------------------------------------------------------------------
4342
TYPE(ValueList_t), POINTER :: List
4343
CHARACTER(LEN=*) :: Name
4344
REAL(KIND=dp) :: F
4345
LOGICAL, OPTIONAL :: Found,UnfoundFatal
4346
REAL(KIND=dp), OPTIONAL :: x,y,z,DefValue
4347
REAL(KIND=dp), OPTIONAL :: minv,maxv
4348
!------------------------------------------------------------------------------
4349
TYPE(Variable_t), POINTER :: Variable
4350
TYPE(ValueListEntry_t), POINTER :: ptr
4351
REAL(KIND=dp) :: xx,yy,zz
4352
INTEGER :: i,j,k,n
4353
!------------------------------------------------------------------------------
4354
IF(PRESENT(DefValue)) THEN
4355
F = DefValue
4356
ELSE
4357
F = 0.0_dp
4358
END IF
4359
4360
ptr => ListFind(List,Name,Found)
4361
IF (.NOT.ASSOCIATED(ptr) ) THEN
4362
IF(PRESENT(UnfoundFatal)) THEN
4363
IF(UnfoundFatal) THEN
4364
WRITE(Message, '(A,A)') "Failed to find constant real: ",Name
4365
CALL Fatal("ListGetConstReal", Message)
4366
END IF
4367
END IF
4368
RETURN
4369
END IF
4370
4371
SELECT CASE(ptr % TYPE)
4372
4373
CASE( LIST_TYPE_CONSTANT_SCALAR )
4374
4375
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
4376
CALL Fatal( 'ListGetConstReal', 'Value type for property ['//TRIM(Name)//&
4377
'] not used consistently.')
4378
END IF
4379
F = ptr % Coeff * ptr % Fvalues(1,1,1)
4380
4381
CASE( LIST_TYPE_CONSTANT_SCALAR_STR )
4382
4383
F = ptr % Coeff * GetMatcReal(ptr % Cvalue)
4384
4385
CASE( LIST_TYPE_CONSTANT_SCALAR_PROC )
4386
4387
IF ( ptr % PROCEDURE == 0 ) THEN
4388
CALL Fatal( 'ListGetConstReal', 'Value type for property ['//TRIM(Name)//&
4389
'] not used consistently.')
4390
END IF
4391
4392
xx = 0.0_dp
4393
yy = 0.0_dp
4394
zz = 0.0_dp
4395
IF ( PRESENT(x) ) xx = x
4396
IF ( PRESENT(y) ) yy = y
4397
IF ( PRESENT(z) ) zz = z
4398
CALL ListPushActiveName(Name)
4399
F = Ptr % Coeff * &
4400
ExecConstRealFunction( ptr % PROCEDURE,CurrentModel,xx,yy,zz )
4401
CALL ListPopActiveName()
4402
4403
CASE( LIST_TYPE_VARIABLE_SCALAR, LIST_TYPE_VARIABLE_SCALAR_STR )
4404
CALL Fatal('ListGetConstReal','Constant cannot depend on variables: '//TRIM(Name))
4405
4406
CASE DEFAULT
4407
CALL Fatal('ListGetConstReal','Invalid list type for: '//TRIM(Name))
4408
4409
END SELECT
4410
4411
IF ( PRESENT( minv ) ) THEN
4412
IF ( F < minv ) THEN
4413
WRITE( Message, *) 'Given VALUE ', F, ' for property: ', '[', TRIM(Name),']', &
4414
' smaller than given minimum: ', minv
4415
CALL Fatal( 'ListGetInteger', Message )
4416
END IF
4417
END IF
4418
4419
IF ( PRESENT( maxv ) ) THEN
4420
IF ( F > maxv ) THEN
4421
WRITE( Message, *) 'Given VALUE ', F, ' for property: ', '[', TRIM(Name),']', &
4422
' larger than given maximum: ', maxv
4423
CALL Fatal( 'ListGetInteger', Message )
4424
END IF
4425
END IF
4426
!------------------------------------------------------------------------------
4427
END FUNCTION ListGetConstReal
4428
!------------------------------------------------------------------------------
4429
4430
4431
!------------------------------------------------------------------------------
4432
!> Returns a scalar real value, that may depend on other scalar values such as
4433
!> time or timestep size etc.
4434
!------------------------------------------------------------------------------
4435
RECURSIVE FUNCTION ListGetCReal( List, Name, Found, minv, maxv, UnfoundFatal, DefValue ) RESULT(s)
4436
!------------------------------------------------------------------------------
4437
TYPE(ValueList_t), POINTER :: List
4438
CHARACTER(LEN=*) :: Name
4439
REAL(KIND=dp), OPTIONAL :: minv,maxv
4440
LOGICAL, OPTIONAL :: Found,UnfoundFatal
4441
INTEGER, TARGET :: Dnodes(1)
4442
INTEGER, POINTER :: NodeIndexes(:)
4443
REAL(KIND=dp), OPTIONAL :: DefValue
4444
4445
REAL(KIND=dp) :: s
4446
REAL(KIND=dp) :: x(1)
4447
TYPE(Element_t), POINTER :: Element
4448
LOGICAL :: LFound
4449
4450
INTEGER :: n, istat
4451
4452
LFound = .FALSE.
4453
NodeIndexes => Dnodes
4454
n = 1
4455
NodeIndexes(n) = 1
4456
4457
x = 0.0_dp
4458
IF ( ASSOCIATED(List % head) ) THEN
4459
x(1:n) = ListGetReal( List, Name, n, NodeIndexes, LFound, minv=minv, maxv=maxv, &
4460
UnfoundFatal=UnfoundFatal )
4461
END IF
4462
s = x(1)
4463
4464
IF( PRESENT( DefValue ) ) THEN
4465
IF(.NOT. LFound ) s = DefValue
4466
END IF
4467
4468
IF ( PRESENT( Found ) ) Found = LFound
4469
4470
!------------------------------------------------------------------------------
4471
END FUNCTION ListGetCReal
4472
!------------------------------------------------------------------------------
4473
4474
!------------------------------------------------------------------------------
4475
!> Returns a scalar real value, that may depend on other scalar values such as
4476
!> time or timestep size etc.
4477
!------------------------------------------------------------------------------
4478
RECURSIVE FUNCTION ListGetRealAtNode( List, Name, Node, Found, UnfoundFatal ) RESULT(s)
4479
!------------------------------------------------------------------------------
4480
TYPE(ValueList_t), POINTER :: List
4481
CHARACTER(LEN=*) :: Name
4482
INTEGER :: Node
4483
LOGICAL, OPTIONAL :: Found, UnfoundFatal
4484
REAL(KIND=dp) :: s
4485
!-----------------------------------------------------------------------------
4486
INTEGER, TARGET, SAVE :: Dnodes(1)
4487
INTEGER, POINTER :: NodeIndexes(:)
4488
REAL(KIND=dp) :: x(1)
4489
INTEGER, PARAMETER :: one = 1
4490
4491
!$omp threadprivate(Dnodes)
4492
4493
4494
IF ( PRESENT( Found ) ) Found = .FALSE.
4495
4496
IF ( ASSOCIATED(List % Head) ) THEN
4497
NodeIndexes => Dnodes
4498
NodeIndexes(one) = Node
4499
4500
x(1:one) = ListGetReal( List, Name, one, NodeIndexes, Found, UnfoundFatal=UnfoundFatal)
4501
s = x(one)
4502
ELSE
4503
s = 0.0_dp
4504
END IF
4505
4506
!------------------------------------------------------------------------------
4507
END FUNCTION ListGetRealAtNode
4508
!------------------------------------------------------------------------------
4509
4510
4511
!> Get pointer to list of section
4512
!------------------------------------------------------------------------------
4513
FUNCTION ListGetSection( Element, SectionName, Found ) RESULT(lst)
4514
!------------------------------------------------------------------------------
4515
TYPE(ValueList_t), POINTER :: Lst
4516
CHARACTER(LEN=*) :: SectionName
4517
LOGICAL, OPTIONAL :: Found
4518
TYPE(Element_t) :: Element
4519
!------------------------------------------------------------------------------
4520
TYPE(ValueList_t), POINTER :: BodyLst
4521
INTEGER :: id
4522
LOGICAL :: LFound
4523
4524
id = Element % BodyId
4525
IF( id > 0 ) THEN
4526
bodylst => CurrentModel % Bodies(id) % Values
4527
ELSE
4528
NULLIFY( bodylst )
4529
END IF
4530
LFound = .FALSE.
4531
4532
NULLIFY( lst )
4533
4534
SELECT CASE ( SectionName )
4535
4536
CASE( 'body' )
4537
lst => bodylst
4538
Lfound = ASSOCIATED( lst )
4539
4540
CASE( 'material' )
4541
id = ListGetInteger( bodylst, SectionName, LFound )
4542
IF( LFound ) lst => CurrentModel % Materials(id) % Values
4543
4544
CASE( 'body force' )
4545
id = ListGetInteger( bodylst, SectionName, LFound )
4546
IF( LFound ) lst => CurrentModel % BodyForces(id) % Values
4547
4548
CASE( 'initial condition' )
4549
id = ListGetInteger( bodylst, SectionName, LFound )
4550
IF( LFound ) lst => CurrentModel % ICs(id) % Values
4551
4552
CASE( 'equation' )
4553
id = ListGetInteger( bodylst, SectionName, LFound )
4554
IF( LFound ) lst => CurrentModel % Equations(id) % Values
4555
4556
CASE( 'boundary condition' )
4557
IF( ASSOCIATED( Element % BoundaryInfo ) ) THEN
4558
id = Element % BoundaryInfo % Constraint
4559
IF( id > 0 ) THEN
4560
lst => CurrentModel % BCs(id) % Values
4561
LFound = .TRUE.
4562
END IF
4563
END IF
4564
4565
CASE DEFAULT
4566
CALL Fatal('ListGetSection','Unknown section name: '//TRIM(SectionName))
4567
4568
END SELECT
4569
4570
IF( PRESENT( Found ) ) Found = LFound
4571
4572
!------------------------------------------------------------------------------
4573
END FUNCTION ListGetSection
4574
!------------------------------------------------------------------------------
4575
4576
4577
SUBROUTINE ListWarnUnsupportedKeyword( SectionName, Keyword, Found, FatalFound )
4578
4579
CHARACTER(LEN=*) :: SectionName, Keyword
4580
4581
LOGICAL, OPTIONAL :: Found, FatalFound
4582
LOGICAL :: LFound, LFatal
4583
INTEGER :: k
4584
CHARACTER(LEN=LEN(SectionName)) :: str
4585
4586
k = StringToLowerCase( str,SectionName )
4587
4588
LFatal = .FALSE.
4589
IF( PRESENT( FatalFound ) ) LFatal = FatalFound
4590
4591
SELECT CASE ( str ) !TRIM( str ) )
4592
4593
CASE( 'body' )
4594
LFound = ListCheckPresentAnyBody( CurrentModel, Keyword )
4595
4596
CASE( 'material' )
4597
LFound = ListCheckPresentAnyMaterial( CurrentModel, Keyword )
4598
4599
CASE( 'body force' )
4600
LFound = ListCheckPresentAnyBodyForce( CurrentModel, Keyword )
4601
4602
CASE( 'solver' )
4603
LFound = ListCheckPresentAnySolver( CurrentModel, Keyword )
4604
4605
CASE( 'equation' )
4606
LFound = ListCheckPresentAnyEquation( CurrentModel, Keyword )
4607
4608
CASE( 'boundary condition' )
4609
LFound = ListCheckPresentAnyBC( CurrentModel, Keyword )
4610
4611
CASE( 'simulation' )
4612
LFound = ListCheckPresent( CurrentModel % Simulation, Keyword )
4613
4614
CASE( 'constants' )
4615
LFound = ListCheckPresent( CurrentModel % Constants, Keyword )
4616
4617
CASE DEFAULT
4618
CALL Fatal('ListWarnUnsupportedKeyword',&
4619
'Unknown section for "'//TRIM(Keyword)//'": '//TRIM(SectionName))
4620
4621
END SELECT
4622
4623
IF( LFound ) THEN
4624
IF( LFatal ) THEN
4625
CALL Fatal('ListWarnUnsupportedKeyword',&
4626
'Keyword in section "'//TRIM(SectionName)//'" not supported: '//TRIM(Keyword) )
4627
ELSE
4628
CALL Warn('ListWarnUnsupportedKeyword',&
4629
'Keyword in section "'//TRIM(SectionName)//'" not supported: '//TRIM(Keyword) )
4630
END IF
4631
END IF
4632
4633
IF( PRESENT( Found ) ) Found = LFound
4634
4635
END SUBROUTINE ListWarnUnsupportedKeyword
4636
4637
4638
4639
!> Get pointer to list of section
4640
!------------------------------------------------------------------------------
4641
FUNCTION ListGetSectionId( Element, SectionName, Found ) RESULT(id)
4642
!------------------------------------------------------------------------------
4643
INTEGER :: id
4644
CHARACTER(LEN=*) :: SectionName
4645
LOGICAL, OPTIONAL :: Found
4646
TYPE(Element_t) :: Element
4647
!------------------------------------------------------------------------------
4648
TYPE(ValueList_t), POINTER :: BodyLst
4649
INTEGER :: body_id
4650
LOGICAL :: LFound
4651
4652
id = 0
4653
4654
body_id = Element % BodyId
4655
IF( body_id > 0 ) THEN
4656
bodylst => CurrentModel % Bodies(body_id) % Values
4657
ELSE
4658
NULLIFY( bodylst )
4659
END IF
4660
LFound = .FALSE.
4661
4662
SELECT CASE ( SectionName )
4663
4664
CASE( 'body' )
4665
id = body_id
4666
4667
CASE( 'material' )
4668
id = ListGetInteger( bodylst, SectionName, LFound )
4669
4670
CASE( 'body force' )
4671
id = ListGetInteger( bodylst, SectionName, LFound )
4672
4673
CASE( 'initial condition' )
4674
id = ListGetInteger( bodylst, SectionName, LFound )
4675
4676
CASE( 'equation' )
4677
id = ListGetInteger( bodylst, SectionName, LFound )
4678
4679
CASE( 'boundary condition' )
4680
IF( ASSOCIATED( Element % BoundaryInfo ) ) THEN
4681
id = Element % BoundaryInfo % Constraint
4682
END IF
4683
4684
CASE DEFAULT
4685
CALL Fatal('ListGetSection','Unknown section name: '//TRIM(SectionName))
4686
4687
END SELECT
4688
4689
IF( PRESENT( Found ) ) Found = ( id > 0 )
4690
4691
!------------------------------------------------------------------------------
4692
END FUNCTION ListGetSectionId
4693
!------------------------------------------------------------------------------
4694
4695
4696
4697
!------------------------------------------------------------------------------
4698
!> Given a string containing comma-separated variablenames, reads the strings
4699
!> and obtains the corresponding variables to a table.
4700
!------------------------------------------------------------------------------
4701
SUBROUTINE ListParseStrToVars( str, slen, name, count, VarTable, &
4702
SomeAtIp, SomeAtNodes, AllGlobal, DummyCount, List )
4703
!------------------------------------------------------------------------------
4704
CHARACTER(LEN=*) :: str, name
4705
INTEGER :: slen, count
4706
TYPE(VariableTable_t) :: VarTable(:)
4707
LOGICAL :: SomeAtIp, SomeAtNodes, AllGlobal
4708
INTEGER :: DummyCount
4709
TYPE(ValueList_t), POINTER, OPTIONAL :: List
4710
!------------------------------------------------------------------------------
4711
INTEGER :: i,j,k,n,k1,l,l0,l1
4712
TYPE(Variable_t), POINTER :: Var
4713
REAL(KIND=dp) :: Val
4714
LOGICAL :: Found
4715
TYPE(ValueListEntry_t), POINTER :: ptr
4716
4717
SomeAtIp = .FALSE.
4718
SomeAtNodes = .FALSE.
4719
AllGlobal = .TRUE.
4720
4721
count=0
4722
l0=1
4723
IF(slen<=0) RETURN
4724
4725
DO WHILE( .TRUE. )
4726
! Remove zeros ahead
4727
DO WHILE( str(l0:l0) == ' ' )
4728
l0 = l0 + 1
4729
IF ( l0 > slen ) EXIT
4730
END DO
4731
IF ( l0 > slen ) EXIT
4732
4733
! Scan only until next comma
4734
l1 = INDEX( str(l0:slen),',')
4735
IF ( l1 > 0 ) THEN
4736
l1=l0+l1-2
4737
ELSE
4738
l1=slen
4739
END IF
4740
4741
! This is a special case of internal variables that should not be parsed
4742
! to point to actual variables.
4743
IF( count < DummyCount ) THEN
4744
Var => VariableGet( CurrentModel % Variables,TRIM(str(l0:l1)) )
4745
IF(ASSOCIATED(Var)) THEN
4746
CALL Fatal('ListParseStrToVars','Function has '//I2S(DummyCount)//&
4747
' internal variables, use dummy names not: '//str(l0:l1))
4748
END IF
4749
AllGlobal = .FALSE.
4750
count = count + 1
4751
SomeAtIp = .TRUE.
4752
VarTable(count) % Variable => NULL()
4753
VarTable(count) % ParamValue = -1.0_dp
4754
ELSE IF ( str(l0:l1) == 'coordinate' ) THEN
4755
VarTable(count+1) % Variable => VariableGet( CurrentModel % Variables,"coordinate 1")
4756
VarTable(count+2) % Variable => VariableGet( CurrentModel % Variables,"coordinate 2")
4757
VarTable(count+3) % Variable => VariableGet( CurrentModel % Variables,"coordinate 3")
4758
count = count + 3
4759
SomeAtNodes = .TRUE.
4760
AllGlobal = .FALSE.
4761
ELSE
4762
Found = .FALSE.
4763
Var => VariableGet( CurrentModel % Variables,TRIM(str(l0:l1)) )
4764
count = count + 1
4765
IF ( ASSOCIATED( Var ) ) THEN
4766
VarTable(count) % Variable => Var
4767
IF( SIZE( Var % Values ) > Var % Dofs ) AllGlobal = .FALSE.
4768
IF( Var % TYPE == Variable_on_gauss_points ) THEN
4769
SomeAtIp = .TRUE.
4770
ELSE
4771
SomeAtNodes = .TRUE.
4772
END IF
4773
Found = .TRUE.
4774
ELSE IF(l1-l0 > 5) THEN
4775
IF(str(l0:l0+4) == 'prev ') THEN
4776
Var => VariableGet( CurrentModel % Variables,TRIM(str(l0+5:l1)) )
4777
IF( ASSOCIATED( Var ) ) THEN
4778
VarTable(count) % Variable => Var
4779
VarTable(count) % tstep = -1
4780
IF( SIZE( Var % Values ) > Var % Dofs ) AllGlobal = .FALSE.
4781
IF( Var % TYPE == Variable_on_gauss_points ) THEN
4782
SomeAtIp = .TRUE.
4783
ELSE
4784
SomeAtNodes = .TRUE.
4785
END IF
4786
Found = .TRUE.
4787
END IF
4788
END IF
4789
END IF
4790
4791
! Ok, the string was not a variable name maybe it is a pure number
4792
! or another keytword.
4793
IF(.NOT. Found) THEN
4794
IF( VERIFY( str(l0:l1),'-.0123456789eE') == 0 ) THEN
4795
!PRINT *,'We do have a number:',Val
4796
READ(str(l0:l1),*) Val
4797
VarTable(count) % Variable => NULL()
4798
VarTable(count) % ParamValue = Val
4799
ELSE
4800
! Check if the dependency is actually a keyword
4801
Found = .FALSE.
4802
IF(PRESENT(List) ) THEN
4803
ptr => ListFind(List,str(l0:l1),Found)
4804
END IF
4805
IF( Found ) THEN
4806
VarTable(count) % Keyword => ptr
4807
AllGlobal = .FALSE.
4808
SomeAtNodes = .TRUE.
4809
ELSE
4810
CALL Info('ListParseStrToVars','Parsed variable '//I2S(count)//' of '//str(1:slen),Level=3)
4811
CALL Info('ListParseStrToVars','Parse counters: '&
4812
//I2S(l0)//', '//I2S(l1)//', '//I2S(slen),Level=10)
4813
CALL Fatal('ListParseStrToVars', 'Can''t find independent variable:['// &
4814
TRIM(str(l0:l1))//'] for dependent variable:['//TRIM(Name)//']' )
4815
END IF
4816
END IF
4817
END IF
4818
END IF
4819
4820
! New start after the comma
4821
l0 = l1+2
4822
IF ( l0 > slen ) EXIT
4823
END DO
4824
4825
!------------------------------------------------------------------------------
4826
END SUBROUTINE ListParseStrToVars
4827
!------------------------------------------------------------------------------
4828
4829
!-------------------------------------------------------------------------------------
4830
!> Given a table of variables and a node index return the variable values on the node.
4831
!-------------------------------------------------------------------------------------
4832
RECURSIVE SUBROUTINE VarsToValuesOnNodes( VarCount, VarTable, ind, T, count, intvarcount, tStep )
4833
!------------------------------------------------------------------------------
4834
INTEGER :: Varcount
4835
TYPE(VariableTable_t) :: VarTable(:)
4836
INTEGER :: ind
4837
INTEGER :: count
4838
INTEGER, OPTIONAL :: intvarcount
4839
INTEGER, OPTIONAL :: tstep
4840
REAL(KIND=dp) :: T(:)
4841
!------------------------------------------------------------------------------
4842
TYPE(Element_t), POINTER :: Element
4843
INTEGER :: i,j,k,n,k1,l,varsize,vari,vari0,tstep0,dti
4844
TYPE(Variable_t), POINTER :: Var
4845
LOGICAL :: Failed
4846
REAL(KIND=dp), POINTER :: Values(:)
4847
4848
Failed = .FALSE.
4849
4850
! Do not even try to treat the internal variables
4851
vari0 = 0
4852
IF(PRESENT(intvarcount)) vari0 = IntVarCount
4853
count = vari0
4854
4855
tstep0 = 0
4856
IF(PRESENT(tstep)) tstep0 = tstep
4857
4858
DO Vari = vari0+1, VarCount
4859
4860
Var => VarTable(Vari) % Variable
4861
! If we are asked keyword on previous timestep, then previous for that is 2nd previous...
4862
dti = -(tstep0 + VarTable(Vari) % tstep)
4863
4864
IF(.NOT. ASSOCIATED( Var ) ) THEN
4865
count = count + 1
4866
IF(ASSOCIATED( VarTable(Vari) % Keyword ) ) THEN
4867
T(count) = ListGetRealInside( VarTable(Vari) % Keyword,'',ind)
4868
ELSE
4869
T(count) = VarTable(Vari) % ParamValue
4870
END IF
4871
CYCLE
4872
END IF
4873
4874
Varsize = SIZE( Var % Values ) / Var % Dofs
4875
4876
IF( Varsize == 1 ) THEN
4877
DO l=1,Var % DOFs
4878
count = count + 1
4879
T(count) = Var % Values(l)
4880
END DO
4881
ELSE
4882
k1 = ind
4883
4884
IF ( Var % TYPE == Variable_on_gauss_points ) THEN
4885
count = count + Var % DOFs
4886
CYCLE
4887
ELSE IF( Var % TYPE == Variable_on_elements ) THEN
4888
Element => CurrentModel % CurrentElement
4889
IF( ASSOCIATED( Element ) ) THEN
4890
k1 = Element % ElementIndex
4891
ELSE
4892
CALL Fatal('VarsToValuesOnNodes','CurrentElement not associated!')
4893
END IF
4894
ELSE IF ( Var % TYPE == Variable_on_nodes_on_elements ) THEN
4895
Element => CurrentModel % CurrentElement
4896
IF ( ASSOCIATED(Element) ) THEN
4897
k1 = 0
4898
IF ( ASSOCIATED(Element % DGIndexes) ) THEN
4899
n = SIZE(Element % DGIndexes)
4900
DO i=1,n
4901
IF ( Element % NodeIndexes(i)==ind ) THEN
4902
k1 = Element % DGIndexes(i)
4903
EXIT
4904
END IF
4905
END DO
4906
ELSE IF( ASSOCIATED( Element % BoundaryInfo ) ) THEN
4907
BLOCK
4908
TYPE(Element_t), POINTER :: Parent
4909
DO j=1,2
4910
IF(j==1) THEN
4911
Parent => Element % BoundaryInfo % Left
4912
ELSE
4913
Parent => Element % BoundaryInfo % Right
4914
END IF
4915
DO i=1,Parent % TYPE % NumberOfNodes
4916
IF( Parent % NodeIndexes(i) == ind) THEN
4917
k1 = Parent % DGIndexes(i)
4918
EXIT
4919
END IF
4920
END DO
4921
IF( k1 > 0 ) THEN
4922
IF(Var % Perm(k1) > 0) EXIT
4923
END IF
4924
END DO
4925
END BLOCK
4926
END IF
4927
IF( k1 == 0 ) THEN
4928
CALL Fatal('VarsToValueOnNodes','Could not find index '//I2S(ind)//&
4929
' in element '//I2S(Element % ElementIndex)//' for '//TRIM(Var % Name))
4930
END IF
4931
ELSE
4932
CALL Fatal('VarsToValuesOnNodes','CurrentElement not associated!')
4933
END IF
4934
END IF
4935
4936
IF ( ASSOCIATED(Var % Perm) ) k1 = Var % Perm(k1)
4937
4938
IF ( k1 > 0 .AND. k1 <= VarSize ) THEN
4939
Values => Var % Values
4940
IF( dti > 0 ) THEN
4941
IF ( ASSOCIATED(Var % PrevValues) ) THEN
4942
IF ( dti <= SIZE(Var % PrevValues,2)) &
4943
Values => Var % PrevValues(:,dti)
4944
END IF
4945
END IF
4946
DO l=1,Var % DOFs
4947
count = count + 1
4948
T(count) = Values(Var % Dofs*(k1-1)+l)
4949
END DO
4950
ELSE
4951
Failed = .TRUE.
4952
DO l=1,Var % DOFs
4953
count = count + 1
4954
T(count) = HUGE(1.0_dp)
4955
END DO
4956
RETURN
4957
END IF
4958
END IF
4959
END DO
4960
4961
END SUBROUTINE VarsToValuesOnNodes
4962
!------------------------------------------------------------------------------
4963
4964
4965
!-------------------------------------------------------------------------------------
4966
!> Check which variables actually are on nodal ones.
4967
!> Didn't want to crowd the previous routine.
4968
!-------------------------------------------------------------------------------------
4969
SUBROUTINE VarsToValuesOnNodesWhich( VarCount, VarTable, IsNodalVar, count )
4970
!------------------------------------------------------------------------------
4971
INTEGER :: Varcount
4972
TYPE(VariableTable_t) :: VarTable(:)
4973
INTEGER :: count
4974
LOGICAL :: IsNodalVar(:)
4975
!------------------------------------------------------------------------------
4976
INTEGER :: vari
4977
TYPE(Variable_t), POINTER :: Var
4978
LOGICAL :: Failed
4979
4980
count = 0
4981
4982
DO Vari = 1, VarCount
4983
Var => VarTable(Vari) % Variable
4984
4985
IF(.NOT. ASSOCIATED( Var ) ) THEN
4986
count = count + 1
4987
IsNodalVar(count) = .FALSE.
4988
ELSE IF( SIZE(Var % Values) / Var % Dofs == 1 ) THEN
4989
IsNodalVar(count+1:count+var % dofs) = .FALSE.
4990
count = count + var % dofs
4991
ELSE
4992
IF ( Var % TYPE == Variable_on_gauss_points ) THEN
4993
IsNodalVar(count+1:count+var%dofs) = .FALSE.
4994
count = count + Var % DOFs
4995
ELSE
4996
IsNodalVar(count+1:count+var%dofs) = .TRUE.
4997
count = count + Var % DOFs
4998
END IF
4999
END IF
5000
END DO
5001
5002
END SUBROUTINE VarsToValuesOnNodesWhich
5003
!------------------------------------------------------------------------------
5004
5005
5006
5007
!------------------------------------------------------------------------------
5008
!> Some variable may be given on the IP points of the bullk only. In that case
5009
!> we need to solve a small linear system in each element to map the values to
5010
!> the nodes, and further to the integration point defined by Basis.
5011
!------------------------------------------------------------------------------
5012
FUNCTION InterpolateIPVariableToBoundary( Element, Basis, Var, dof ) RESULT ( T )
5013
!------------------------------------------------------------------------------
5014
TYPE(Element_t), POINTER :: Element
5015
REAL(KIND=dp) :: Basis(:)
5016
TYPE(Variable_t), POINTER :: Var
5017
INTEGER, OPTIONAL :: dof
5018
REAL(KIND=dp) :: T
5019
!------------------------------------------------------------------------------
5020
TYPE(Element_t), POINTER :: Parent
5021
INTEGER :: ipar, npar, i, j, n, np, nip, dofs
5022
REAL(KIND=dp), ALLOCATABLE :: fip(:),fdg(:)
5023
5024
! We have to provide interface for this as otherwise we would create a
5025
! cyclic dependence.
5026
INTERFACE
5027
SUBROUTINE Ip2DgFieldInElement( Mesh, Parent, nip, fip, np, fdg )
5028
USE Types
5029
TYPE(Mesh_t), POINTER :: Mesh
5030
TYPE(Element_t), POINTER :: Parent
5031
INTEGER :: nip, np
5032
REAL(KIND=dp) :: fip(:), fdg(:)
5033
END SUBROUTINE Ip2DgFieldInElement
5034
END INTERFACE
5035
5036
T = 0.0_dp
5037
n = Element % TYPE % NumberOfNodes
5038
npar = 0.0_dp
5039
dofs = Var % Dofs
5040
IF(dofs > 1) THEN
5041
IF(.NOT. PRESENT(dof)) THEN
5042
CALL Fatal('InterpolateIPVariableToBoundary','Give component of ip variable!')
5043
END IF
5044
END IF
5045
5046
! Go through both potential parents. If we find the information in both then
5047
! take on average. Otherwise use one-side interpolation.
5048
DO ipar = 1,2
5049
IF( ipar == 1 ) THEN
5050
Parent => Element % BoundaryInfo % Left
5051
ELSE
5052
Parent => Element % BoundaryInfo % Right
5053
END IF
5054
IF(.NOT. ASSOCIATED( Parent ) ) CYCLE
5055
5056
i = Parent % ElementIndex
5057
j = Var % Perm(i)
5058
nip = Var % Perm(i+1) - j
5059
IF( nip == 0 ) CYCLE
5060
np = Parent % TYPE % NumberOfNodes
5061
5062
ALLOCATE( fip(nip), fdg(np) )
5063
5064
IF( dofs > 1 ) THEN
5065
DO i=1,nip
5066
fip(i) = Var % Values(dofs*(j+i-1)+dof)
5067
END DO
5068
ELSE
5069
fip(1:nip) = Var % Values(j+1:j+nip)
5070
END IF
5071
fdg(1:np) = 0.0_dp
5072
5073
CALL Ip2DgFieldInElement( CurrentModel % Mesh, Parent, nip, fip, np, fdg )
5074
npar = npar + 1
5075
5076
! Use basis functions of the boundary to map stuff from nodes to IP points.
5077
DO i=1,n
5078
DO j=1,np
5079
IF( Element % NodeIndexes(i) == Parent % NodeIndexes(j) ) THEN
5080
T = T + Basis(i) * fdg(j)
5081
EXIT
5082
END IF
5083
END DO
5084
END DO
5085
5086
DEALLOCATE( fip, fdg )
5087
END DO
5088
5089
! Now take the average, if needed.
5090
IF( npar == 2 ) T = T / 2
5091
5092
END FUNCTION InterpolateIPVariableToBoundary
5093
!------------------------------------------------------------------------------
5094
5095
5096
5097
!-------------------------------------------------------------------------------------
5098
!> Given a table of variables return the variable values on the gauss point.
5099
!> This only deals with the gauss point variables, all other are already treated.
5100
!-------------------------------------------------------------------------------------
5101
SUBROUTINE VarsToValuesOnIps( VarCount, VarTable, T, count, ind, Basis, intvarcount, tstep)
5102
!------------------------------------------------------------------------------
5103
INTEGER :: Varcount
5104
TYPE(VariableTable_t) :: VarTable(:)
5105
INTEGER :: count
5106
REAL(KIND=dp) :: T(:)
5107
INTEGER, OPTIONAL :: ind
5108
REAL(KIND=dp), OPTIONAL :: Basis(:)
5109
INTEGER, OPTIONAL :: intvarcount
5110
INTEGER, OPTIONAL :: tstep
5111
!------------------------------------------------------------------------------
5112
TYPE(Element_t), POINTER :: Element
5113
INTEGER :: i,j,k,n,k1,l,varsize,vari,vari0,dti,tstep0
5114
TYPE(Variable_t), POINTER :: Var
5115
LOGICAL :: Failed
5116
REAL(KIND=dp), POINTER :: Values(:)
5117
5118
Failed = .FALSE.
5119
vari0 = 0
5120
IF( PRESENT(intvarcount)) THEN
5121
vari0 = intvarcount
5122
END IF
5123
count = vari0
5124
5125
tstep0 = 0
5126
IF(PRESENT(tstep)) tstep0 = tstep
5127
5128
DO Vari = vari0+1, VarCount
5129
5130
Var => VarTable(Vari) % Variable
5131
5132
IF(.NOT. ASSOCIATED( Var ) ) THEN
5133
count = count + 1
5134
T(count) = VarTable(Vari) % ParamValue
5135
CYCLE
5136
END IF
5137
5138
dti = -(tstep0 + VarTable(Vari) % tstep)
5139
Varsize = SIZE( Var % Values ) / Var % Dofs
5140
5141
k1 = 0
5142
IF ( Var % TYPE == Variable_on_gauss_points ) THEN
5143
Element => CurrentModel % CurrentElement
5144
i = Element % ElementIndex
5145
n = Var % Perm(i+1) - Var % Perm(i)
5146
5147
IF( n > 0 ) THEN
5148
IF(.NOT. PRESENT(ind) ) THEN
5149
CALL Fatal('VarsToValuesOnIPs','Ip field '//TRIM(Var % Name)//' given but no ip point given as parameter!')
5150
ELSE IF( n < ind ) THEN
5151
CALL Warn('VarsToValuesOnIPs','Too few integration points ('&
5152
//I2S(n)//' vs. '//I2S(ind)//') tabulated!')
5153
ELSE
5154
k1 = Var % Perm(i) + ind
5155
END IF
5156
ELSE
5157
IF( ASSOCIATED( Element % BoundaryInfo ) ) THEN
5158
IF(.NOT. PRESENT(Basis) ) THEN
5159
CALL Fatal('VarsToValuesOnIps','We need the "Basis" parameter to map stuff to boundaries!')
5160
END IF
5161
IF( Var % Dofs > 1 ) THEN
5162
DO l=1,Var % Dofs
5163
T(count+l) = InterpolateIPVariableToBoundary( Element, Basis, Var, l )
5164
END DO
5165
ELSE
5166
T(count+1) = InterpolateIPVariableToBoundary( Element, Basis, Var )
5167
END IF
5168
ELSE
5169
CALL Warn('VarsToValuesOnIPs','Could not find dependent IP variable: '//TRIM(Var % Name))
5170
END IF
5171
END IF
5172
END IF
5173
5174
IF ( k1 > 0 ) THEN
5175
Values => Var % Values
5176
IF( dti > 0 ) THEN
5177
IF ( ASSOCIATED(Var % PrevValues) ) THEN
5178
IF ( dti <= SIZE(Var % PrevValues,2)) &
5179
Values => Var % PrevValues(:,dti)
5180
END IF
5181
END IF
5182
5183
DO l=1,Var % DOFs
5184
count = count + 1
5185
T(count) = Values(Var % Dofs*(k1-1)+l)
5186
END DO
5187
ELSE
5188
count = count + Var % Dofs
5189
END IF
5190
END DO
5191
5192
END SUBROUTINE VarsToValuesOnIps
5193
!------------------------------------------------------------------------------
5194
5195
5196
5197
!------------------------------------------------------------------------------
5198
SUBROUTINE ListParseStrToValues( str, slen, ind, name, T, count, AllGlobal )
5199
!------------------------------------------------------------------------------
5200
CHARACTER(LEN=*) :: str, name
5201
REAL(KIND=dp) :: T(:)
5202
INTEGER :: slen, count, ind
5203
LOGICAL :: AllGlobal
5204
!------------------------------------------------------------------------------
5205
TYPE(Element_t), POINTER :: Element
5206
INTEGER :: i,j,k,n,k1,l,l0,l1
5207
TYPE(Variable_t), POINTER :: Variable, CVar
5208
5209
AllGlobal = .TRUE.
5210
5211
count=0
5212
l0=1
5213
IF(slen<=0) RETURN
5214
5215
DO WHILE( .TRUE. )
5216
DO WHILE( str(l0:l0) == ' ' )
5217
l0 = l0 + 1
5218
IF ( l0 > slen ) EXIT
5219
END DO
5220
IF ( l0 > slen ) EXIT
5221
5222
l1 = INDEX( str(l0:slen),',')
5223
IF ( l1 > 0 ) THEN
5224
l1=l0+l1-2
5225
ELSE
5226
l1=slen
5227
END IF
5228
5229
IF ( str(l0:l1) /= 'coordinate' ) THEN
5230
Variable => VariableGet( CurrentModel % Variables,TRIM(str(l0:l1)) )
5231
IF ( .NOT. ASSOCIATED( Variable ) ) THEN
5232
CALL Info('ListParseStrToValues','Parsed variable '//I2S(count+1)//' of '//str(1:slen),Level=3)
5233
CALL Info('ListParseStrToValues','Parse counters: '&
5234
//I2S(l0)//', '//I2S(l1)//', '//I2S(slen),Level=10)
5235
CALL Fatal('ListParseStrToValues','Can''t find independent variable:['// &
5236
TRIM(str(l0:l1))//'] for dependent variable:['//TRIM(Name)//']')
5237
END IF
5238
IF( SIZE( Variable % Values ) > Variable % Dofs ) AllGlobal = .FALSE.
5239
ELSE
5240
AllGlobal = .FALSE.
5241
Variable => VariableGet( CurrentModel % Variables,'Coordinate 1' )
5242
END IF
5243
5244
IF( Variable % TYPE == Variable_on_gauss_points ) THEN
5245
DO l=1,Variable % DOFs
5246
count = count + 1
5247
T(count) = HUGE(1.0_dp)
5248
END DO
5249
5250
l0 = l1+2
5251
IF ( l0 > slen ) EXIT
5252
CYCLE
5253
END IF
5254
5255
k1 = ind
5256
5257
IF ( Variable % TYPE == Variable_on_nodes_on_elements ) THEN
5258
Element => CurrentModel % CurrentElement
5259
IF ( ASSOCIATED(Element) ) THEN
5260
IF ( ASSOCIATED(Element % DGIndexes) ) THEN
5261
n = SIZE(Element % DGIndexes)
5262
DO i=1,n
5263
IF ( Element % NodeIndexes(i)==ind ) THEN
5264
k1 = Element % DGIndexes(i)
5265
EXIT
5266
END IF
5267
END DO
5268
END IF
5269
END IF
5270
END IF
5271
IF ( ASSOCIATED(Variable % Perm) ) k1 = Variable % Perm(k1)
5272
5273
IF ( k1>0 .AND. k1<=SIZE(Variable % Values) ) THEN
5274
IF ( str(l0:l1) == 'coordinate' ) THEN
5275
CVar => VariableGet( CurrentModel % Variables, 'Coordinate 1' )
5276
count = count + 1
5277
T(1) = CVar % Values(k1)
5278
CVar => VariableGet( CurrentModel % Variables, 'Coordinate 2' )
5279
count = count + 1
5280
T(2) = CVar % Values(k1)
5281
CVar => VariableGet( CurrentModel % Variables, 'Coordinate 3' )
5282
count = count + 1
5283
T(3) = CVar % Values(k1)
5284
ELSE
5285
IF ( Variable % DOFs == 1 ) THEN
5286
count = count + 1
5287
T(count) = Variable % Values(k1)
5288
ELSE
5289
DO l=1,Variable % DOFs
5290
count = count + 1
5291
T(count) = Variable % Values(Variable % DOFs*(k1-1)+l)
5292
END DO
5293
END IF
5294
END IF
5295
ELSE
5296
5297
count = count + 1
5298
IF ( ASSOCIATED(Variable % Perm) ) THEN
5299
T(count) = HUGE(1.0_dp)
5300
EXIT
5301
ELSE
5302
T(count) = Variable % Values(1)
5303
END IF
5304
END IF
5305
5306
l0 = l1+2
5307
IF ( l0 > slen ) EXIT
5308
END DO
5309
5310
!------------------------------------------------------------------------------
5311
END SUBROUTINE ListParseStrToValues
5312
!------------------------------------------------------------------------------
5313
5314
5315
!------------------------------------------------------------------------------
5316
FUNCTION ListCheckGlobal( ptr ) RESULT ( IsGlobal )
5317
!------------------------------------------------------------------------------
5318
TYPE(ValueListEntry_t), POINTER :: ptr
5319
LOGICAL :: IsGlobal
5320
!------------------------------------------------------------------------------
5321
TYPE(Element_t), POINTER :: Element
5322
INTEGER :: ind,i,j,k,n,k1,l,l0,l1,ll,count
5323
TYPE(Variable_t), POINTER :: Variable, CVar
5324
INTEGER :: slen
5325
5326
IsGlobal = .TRUE.
5327
5328
IF(.NOT.ASSOCIATED(ptr)) THEN
5329
CALL Warn('ListCheckGlobal','ptr not associated!')
5330
RETURN
5331
END IF
5332
5333
5334
IF( ptr % TYPE == LIST_TYPE_CONSTANT_SCALAR_STR ) THEN
5335
RETURN
5336
5337
ELSE IF( ptr % TYPE == LIST_TYPE_CONSTANT_SCALAR .OR. &
5338
ptr % TYPE == LIST_TYPE_VARIABLE_SCALAR .OR. &
5339
ptr % TYPE == LIST_TYPE_VARIABLE_SCALAR_STR ) THEN
5340
5341
5342
IF ( ptr % PROCEDURE /= 0 ) THEN
5343
IsGlobal = .FALSE.
5344
RETURN
5345
END IF
5346
5347
slen = ptr % DepNameLen
5348
5349
IF( slen > 0 ) THEN
5350
count = 0
5351
l0 = 1
5352
DO WHILE( .TRUE. )
5353
5354
DO WHILE( ptr % DependName(l0:l0) == ' ' )
5355
l0 = l0 + 1
5356
END DO
5357
IF ( l0 > slen ) EXIT
5358
5359
l1 = INDEX( ptr % DependName(l0:slen),',')
5360
IF ( l1 > 0 ) THEN
5361
l1=l0+l1-2
5362
ELSE
5363
l1=slen
5364
END IF
5365
5366
count = count + 1
5367
5368
IF ( ptr % DependName(l0:l1) /= 'coordinate' ) THEN
5369
Variable => VariableGet( CurrentModel % Variables,TRIM(ptr % DependName(l0:l1)) )
5370
IF ( .NOT. ASSOCIATED( Variable ) ) THEN
5371
CALL Info('ListCheckGlobal','Parsed variable '//I2S(count)//' of '&
5372
//ptr % DependName(1:slen),Level=3)
5373
CALL Info('ListCheckGlobal','Parse counters: '&
5374
//I2S(l0)//', '//I2S(l1)//', '//I2S(slen),Level=10)
5375
5376
WRITE( Message, * ) 'Can''t find independent variable:[', &
5377
TRIM(ptr % DependName(l0:l1)),']'
5378
CALL Fatal( 'ListCheckGlobal', Message )
5379
END IF
5380
5381
IF( SIZE( Variable % Values ) > 1 ) THEN
5382
IsGlobal = .FALSE.
5383
RETURN
5384
END IF
5385
5386
ELSE
5387
IsGlobal = .FALSE.
5388
EXIT
5389
END IF
5390
5391
l0 = l1+2
5392
IF ( l0 > slen ) EXIT
5393
END DO
5394
ELSE
5395
IsGlobal = .FALSE.
5396
END IF
5397
END IF
5398
5399
5400
!------------------------------------------------------------------------------
5401
END FUNCTION ListCheckGlobal
5402
!------------------------------------------------------------------------------
5403
5404
5405
5406
!------------------------------------------------------------------------------
5407
FUNCTION ListCheckAllGlobal( List, name ) RESULT ( AllGlobal )
5408
!------------------------------------------------------------------------------
5409
TYPE(ValueList_t), POINTER :: List
5410
CHARACTER(LEN=*) :: name
5411
LOGICAL :: AllGlobal
5412
!------------------------------------------------------------------------------
5413
TYPE(ValueListEntry_t), POINTER :: ptr
5414
TYPE(Element_t), POINTER :: Element
5415
INTEGER :: ind,i,j,k,n,k1,l,l0,l1
5416
TYPE(Variable_t), POINTER :: Variable, CVar
5417
INTEGER :: slen
5418
5419
AllGlobal = .TRUE.
5420
5421
IF(.NOT.ASSOCIATED(List)) RETURN
5422
5423
ptr => List % Head
5424
IF(.NOT.ASSOCIATED(ptr)) RETURN
5425
5426
AllGlobal = ListCheckGlobal( ptr )
5427
5428
!------------------------------------------------------------------------------
5429
END FUNCTION ListCheckAllGlobal
5430
!------------------------------------------------------------------------------
5431
5432
!------------------------------------------------------------------------------
5433
!> Check Gets a real valued parameter in each node of an element.
5434
!------------------------------------------------------------------------------
5435
RECURSIVE FUNCTION ListCheckIsConstant( List,Name,Found) RESULT( IsConstant )
5436
!------------------------------------------------------------------------------
5437
TYPE(ValueList_t), POINTER :: List
5438
CHARACTER(LEN=*) :: Name
5439
LOGICAL, OPTIONAL :: Found
5440
LOGICAL :: IsConstant
5441
!------------------------------------------------------------------------------
5442
TYPE(ValueListEntry_t), POINTER :: ptr
5443
5444
IsConstant = .FALSE.
5445
ptr => ListFind(List,Name,Found)
5446
IF (.NOT.ASSOCIATED(ptr) ) RETURN
5447
5448
SELECT CASE(ptr % TYPE)
5449
CASE( LIST_TYPE_CONSTANT_SCALAR, &
5450
LIST_TYPE_CONSTANT_TENSOR, &
5451
LIST_TYPE_LOGICAL, &
5452
LIST_TYPE_INTEGER )
5453
IsConstant = .TRUE.
5454
END SELECT
5455
IF( ptr % PROCEDURE /= 0) IsConstant = .FALSE.
5456
5457
END FUNCTION ListCheckIsConstant
5458
!------------------------------------------------------------------------------
5459
5460
5461
!------------------------------------------------------------------------------
5462
!> Gets a real valued parameter in each node of an element.
5463
!------------------------------------------------------------------------------
5464
RECURSIVE FUNCTION ListGetReal( List,Name,N,NodeIndexes,Found,minv,maxv,UnfoundFatal ) RESULT(F)
5465
!------------------------------------------------------------------------------
5466
TYPE(ValueList_t), POINTER :: List
5467
CHARACTER(LEN=*) :: Name
5468
INTEGER :: N,NodeIndexes(:)
5469
REAL(KIND=dp) :: F(N)
5470
LOGICAL, OPTIONAL :: Found, UnfoundFatal
5471
REAL(KIND=dp), OPTIONAL :: minv,maxv
5472
!------------------------------------------------------------------------------
5473
TYPE(Variable_t), POINTER :: Variable, CVar, TVar
5474
TYPE(ValueListEntry_t), POINTER :: ptr
5475
REAL(KIND=dp) :: T(MAX_FNC)
5476
TYPE(VariableTable_t) :: VarTable(MAX_FNC)
5477
INTEGER :: i,j,k,k1,l,l0,l1,lsize, VarCount
5478
LOGICAL :: AllGlobal, SomeAtIp, SomeAtNodes
5479
! INTEGER :: TID, OMP_GET_THREAD_NUM
5480
!------------------------------------------------------------------------------
5481
! TID = 0
5482
! !$ TID=OMP_GET_THREAD_NUM()
5483
F = 0.0_dp
5484
ptr => ListFind(List,Name,Found)
5485
IF (.NOT.ASSOCIATED(ptr) ) THEN
5486
IF(PRESENT(UnfoundFatal)) THEN
5487
IF(UnfoundFatal) THEN
5488
WRITE(Message, '(A,A)') "Failed to find real: ",Name
5489
CALL Fatal("ListGetReal", Message)
5490
END IF
5491
END IF
5492
RETURN
5493
END IF
5494
5495
5496
SELECT CASE(ptr % TYPE)
5497
5498
CASE( LIST_TYPE_CONSTANT_SCALAR )
5499
5500
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
5501
CALL Fatal( 'ListGetReal', 'Value type for property ['//TRIM(Name)//&
5502
'] not used consistently.')
5503
END IF
5504
F = ptr % Coeff * ptr % Fvalues(1,1,1)
5505
5506
5507
CASE( LIST_TYPE_VARIABLE_SCALAR )
5508
5509
CALL ListPushActiveName(Name)
5510
5511
CALL ListParseStrToVars( Ptr % DependName, Ptr % DepNameLen, Name, VarCount, VarTable, &
5512
SomeAtIp, SomeAtNodes, AllGlobal, 0, List )
5513
IF( SomeAtIp ) THEN
5514
CALL Fatal('ListGetReal','Function cannot deal with variables on IPs!')
5515
END IF
5516
5517
DO i=1,n
5518
k = NodeIndexes(i)
5519
5520
CALL VarsToValuesOnNodes( VarCount, VarTable, k, T, j )
5521
5522
IF ( .NOT. ANY( T(1:j)==HUGE(1.0_dp) ) ) THEN
5523
IF ( ptr % PROCEDURE /= 0 ) THEN
5524
F(i) = ptr % Coeff * &
5525
ExecRealFunction( ptr % PROCEDURE,CurrentModel, k, T )
5526
ELSE
5527
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
5528
CALL Fatal( 'ListGetReal', 'Value type for property ['//TRIM(Name)//&
5529
'] not used consistently.')
5530
END IF
5531
F(i) = ptr % Coeff * &
5532
InterpolateCurve( ptr % TValues,ptr % FValues(1,1,:), &
5533
T(1), ptr % CubicCoeff )
5534
IF( AllGlobal) THEN
5535
F(2:n) = F(1)
5536
EXIT
5537
END IF
5538
END IF
5539
END IF
5540
END DO
5541
CALL ListPopActiveName()
5542
5543
5544
CASE( LIST_TYPE_CONSTANT_SCALAR_STR )
5545
TVar => VariableGet( CurrentModel % Variables, 'Time' )
5546
F(1:n) = ptr % Coeff * GetMatcReal(ptr % Cvalue,1,Tvar % values,'st')
5547
5548
CASE( LIST_TYPE_VARIABLE_SCALAR_STR )
5549
5550
CALL ListParseStrToVars( Ptr % DependName, Ptr % DepNameLen, Name, VarCount, &
5551
VarTable, SomeAtIp, SomeAtNodes, AllGlobal, 0, List )
5552
IF( SomeAtIp ) THEN
5553
CALL Fatal('ListGetReal','Function cannot deal with variables on IPs!')
5554
END IF
5555
5556
5557
DO i=1,n
5558
k = NodeIndexes(i)
5559
5560
CALL VarsToValuesOnNodes( VarCount, VarTable, k, T, j )
5561
5562
IF ( .NOT. ptr % LuaFun ) THEN
5563
IF ( .NOT. ANY( T(1:j)==HUGE(1.0_dp) ) ) THEN
5564
F(i) = Ptr % Coeff * GetMatcReal(ptr % Cvalue,j,T)
5565
END IF
5566
ELSE
5567
CALL ElmerEvalLua(LuaState, ptr, T, F(i), j )
5568
END IF
5569
5570
IF( AllGlobal ) THEN
5571
F(2:n) = F(1)
5572
EXIT
5573
END IF
5574
5575
END DO
5576
5577
CASE( LIST_TYPE_CONSTANT_SCALAR_PROC )
5578
5579
IF ( ptr % PROCEDURE == 0 ) THEN
5580
CALL Fatal( 'ListGetReal', 'Value type for property ['//TRIM(Name)//&
5581
'] not used consistently.')
5582
END IF
5583
5584
CALL ListPushActiveName(name)
5585
DO i=1,n
5586
F(i) = Ptr % Coeff * &
5587
ExecConstRealFunction( ptr % PROCEDURE,CurrentModel, &
5588
CurrentModel % Mesh % Nodes % x( NodeIndexes(i) ), &
5589
CurrentModel % Mesh % Nodes % y( NodeIndexes(i) ), &
5590
CurrentModel % Mesh % Nodes % z( NodeIndexes(i) ) )
5591
END DO
5592
CALL ListPopActiveName()
5593
5594
END SELECT
5595
5596
IF ( PRESENT( minv ) ) THEN
5597
IF ( MINVAL(F(1:n)) < minv ) THEN
5598
WRITE( Message,*) 'Given VALUE ', MINVAL(F(1:n)), ' for property: ', '[', TRIM(Name),']', &
5599
' smaller than given minimum: ', minv
5600
CALL Fatal( 'ListGetReal', Message )
5601
END IF
5602
END IF
5603
5604
IF ( PRESENT( maxv ) ) THEN
5605
IF ( MAXVAL(F(1:n)) > maxv ) THEN
5606
WRITE( Message,*) 'Given VALUE ', MAXVAL(F(1:n)), ' for property: ', '[', TRIM(Name),']', &
5607
' larger than given maximum ', maxv
5608
CALL Fatal( 'ListGetReal', Message )
5609
END IF
5610
END IF
5611
END FUNCTION ListGetReal
5612
!------------------------------------------------------------------------------
5613
5614
5615
!------------------------------------------------------------------------------
5616
!> Gets a real valued parameter for one node. This is a special
5617
!> version of this routine only for keywords depending on keywords.
5618
!------------------------------------------------------------------------------
5619
RECURSIVE FUNCTION ListGetRealInside( ptr,Name,NodeIndex) RESULT(F)
5620
!------------------------------------------------------------------------------
5621
TYPE(ValueListEntry_t), POINTER :: ptr
5622
CHARACTER(LEN=*) :: Name
5623
INTEGER :: NodeIndex
5624
REAL(KIND=dp) :: F
5625
!------------------------------------------------------------------------------
5626
TYPE(Variable_t), POINTER :: Variable, CVar, TVar
5627
REAL(KIND=dp) :: T(MAX_FNC)
5628
TYPE(VariableTable_t) :: VarTable(MAX_FNC)
5629
INTEGER :: j, VarCount
5630
LOGICAL :: AllGlobal, SomeAtIp, SomeAtNodes
5631
! INTEGER :: TID, OMP_GET_THREAD_NUM
5632
!------------------------------------------------------------------------------
5633
! TID = 0
5634
! !$ TID=OMP_GET_THREAD_NUM()
5635
F = 0.0_dp
5636
5637
SELECT CASE(ptr % TYPE)
5638
5639
CASE( LIST_TYPE_CONSTANT_SCALAR )
5640
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
5641
CALL Fatal( 'ListGetRealInside', 'Value type for property ['//TRIM(Name)// &
5642
'] not used consistently.' )
5643
END IF
5644
F = ptr % Coeff * ptr % Fvalues(1,1,1)
5645
5646
CASE( LIST_TYPE_VARIABLE_SCALAR )
5647
CALL ListParseStrToVars( Ptr % DependName, Ptr % DepNameLen, Name, VarCount, VarTable, &
5648
SomeAtIp, SomeAtNodes, AllGlobal, 0 )
5649
IF( SomeAtIp ) THEN
5650
CALL Fatal('ListGetRealInside','Function cannot deal with variables on IPs!')
5651
END IF
5652
5653
CALL VarsToValuesOnNodes( VarCount, VarTable, NodeIndex, T, j )
5654
5655
IF ( .NOT. ANY( T(1:j)==HUGE(1.0_dp) ) ) THEN
5656
IF ( ptr % PROCEDURE /= 0 ) THEN
5657
F = ptr % Coeff * &
5658
ExecRealFunction( ptr % PROCEDURE,CurrentModel, NodeIndex, T )
5659
ELSE
5660
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
5661
CALL Fatal( 'ListGetRealInside','Value type for property ['//TRIM(Name)// &
5662
'] not used consistently.' )
5663
END IF
5664
F = ptr % Coeff * &
5665
InterpolateCurve( ptr % TValues,ptr % FValues(1,1,:), &
5666
T(1), ptr % CubicCoeff )
5667
END IF
5668
END IF
5669
5670
CASE( LIST_TYPE_CONSTANT_SCALAR_STR )
5671
TVar => VariableGet( CurrentModel % Variables, 'Time' )
5672
F = ptr % Coeff * GetMatcReal(ptr % Cvalue,1,Tvar % values,'st')
5673
5674
CASE( LIST_TYPE_VARIABLE_SCALAR_STR )
5675
5676
CALL ListParseStrToVars( Ptr % DependName, Ptr % DepNameLen, Name, VarCount, &
5677
VarTable, SomeAtIp, SomeAtNodes, AllGlobal, 0 )
5678
IF( SomeAtIp ) THEN
5679
CALL Fatal('ListGetRealInside','Function cannot deal with variables on IPs!')
5680
END IF
5681
5682
CALL VarsToValuesOnNodes( VarCount, VarTable, NodeIndex, T, j )
5683
IF ( .NOT. ptr % LuaFun ) THEN
5684
IF ( .NOT. ANY( T(1:j)==HUGE(1.0_dp) ) ) THEN
5685
F = Ptr % Coeff * GetMatcReal(ptr % Cvalue,j,T)
5686
END IF
5687
ELSE
5688
CALL ElmerEvalLua(LuaState, ptr, T, F, j )
5689
END IF
5690
5691
CASE( LIST_TYPE_CONSTANT_SCALAR_PROC )
5692
IF ( ptr % PROCEDURE == 0 ) THEN
5693
CALL Fatal('ListGetRealInside','Value type for property ['//TRIM(Name)// &
5694
'] not used consistently.')
5695
END IF
5696
F = Ptr % Coeff * &
5697
ExecConstRealFunction( ptr % PROCEDURE,CurrentModel, &
5698
CurrentModel % Mesh % Nodes % x( NodeIndex ), &
5699
CurrentModel % Mesh % Nodes % y( NodeIndex ), &
5700
CurrentModel % Mesh % Nodes % z( NodeIndex ) )
5701
END SELECT
5702
5703
END FUNCTION ListGetRealInside
5704
!------------------------------------------------------------------------------
5705
5706
5707
!------------------------------------------------------------------------------
5708
!> Gets a real valued parameter in one single point with value x.
5709
!> Optionally also computes the derivative at that point.
5710
!> Note that this uses same logical on sif file as ListGetReal
5711
!> but the variable is just a dummy as the dependent function is
5712
!> assumed to be set inside the code. This should be used with caution
5713
!> is it sets some confusing limitations to the user. The main limitation
5714
!> is the use of just one dependent variable.
5715
!------------------------------------------------------------------------------
5716
RECURSIVE FUNCTION ListGetFun( List,Name,x,Found,minv,maxv,dFdx,eps ) RESULT(F)
5717
!------------------------------------------------------------------------------
5718
TYPE(ValueList_t), POINTER :: List
5719
REAL(KIND=dp), OPTIONAL :: x
5720
REAL(KIND=dp) :: f
5721
CHARACTER(LEN=*), OPTIONAL :: Name
5722
LOGICAL, OPTIONAL :: Found
5723
REAL(KIND=dp), OPTIONAL :: minv,maxv
5724
REAL(KIND=dp), OPTIONAL :: dFdx, eps
5725
!------------------------------------------------------------------------------
5726
TYPE(Variable_t), POINTER :: Variable, CVar, TVar
5727
TYPE(ValueListEntry_t), POINTER :: ptr, prevptr, derptr
5728
REAL(KIND=dp) :: T(1)
5729
INTEGER :: i,j,k,k1,l,l0,l1,lsize
5730
LOGICAL :: AllGlobal, GotIt
5731
REAL(KIND=dp) :: xeps, F2, F1
5732
!------------------------------------------------------------------------------
5733
5734
SAVE prevptr, derptr
5735
5736
IF(.NOT. PRESENT(x) ) THEN
5737
CALL Fatal('ListGetFun','Variable "x" is in fact compulsory!')
5738
END IF
5739
5740
F = 0.0_dp
5741
IF( PRESENT( Name ) ) THEN
5742
ptr => ListFind(List,Name,Found)
5743
IF ( .NOT.ASSOCIATED(ptr) ) RETURN
5744
ELSE
5745
IF(.NOT.ASSOCIATED(List)) RETURN
5746
ptr => List % Head
5747
IF ( .NOT.ASSOCIATED(ptr) ) THEN
5748
CALL Warn('ListGetFun','List entry not associated')
5749
RETURN
5750
END IF
5751
END IF
5752
5753
! Node number not applicable, hence set to zero
5754
k = 0
5755
T(1) = x
5756
5757
! See if we have analytical derivative available.
5758
! This is list-specific, hence memorize it.
5759
IF( PRESENT( DfDx) ) THEN
5760
IF( .NOT. ASSOCIATED( Ptr, PrevPtr ) ) THEN
5761
PrevPtr => Ptr
5762
derPtr => ListFind(List,TRIM(Name)//' Derivative',GotIt )
5763
END IF
5764
END IF
5765
5766
SELECT CASE(ptr % TYPE)
5767
5768
CASE( LIST_TYPE_CONSTANT_SCALAR )
5769
5770
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
5771
CALL Fatal( 'ListGetReal', 'Value type for property ['//TRIM(Name)// &
5772
'] not used consistently.')
5773
END IF
5774
F = ptr % Coeff * ptr % Fvalues(1,1,1)
5775
IF( PRESENT( dFdx ) ) THEN
5776
dFdx = 0.0_dp
5777
END IF
5778
5779
5780
CASE( LIST_TYPE_VARIABLE_SCALAR )
5781
5782
IF ( ptr % PROCEDURE /= 0 ) THEN
5783
CALL ListPushActiveName(name)
5784
F = ExecRealFunction( ptr % PROCEDURE,CurrentModel, k, T(1) )
5785
5786
! Compute derivative at the point if requested
5787
IF( PRESENT( dFdx ) ) THEN
5788
IF( ASSOCIATED( derPtr ) ) THEN
5789
! Analytical derivative available in another UDF
5790
IF(derptr % PROCEDURE /= 0) THEN
5791
dFdx = ExecRealFunction( derptr % PROCEDURE, CurrentModel, k, T(1) )
5792
ELSE
5793
CALL Fatal('ListGetFun','Derivative should be UDF if primary keyword is!')
5794
END IF
5795
ELSE
5796
! Numerical central difference scheme is used for accuracy.
5797
IF( PRESENT( eps ) ) THEN
5798
xeps = eps
5799
ELSE
5800
xeps = 1.0d-8
5801
END IF
5802
T(1) = x - xeps
5803
F1 = ExecRealFunction( ptr % PROCEDURE,CurrentModel, k, T(1) )
5804
T(1) = x + xeps
5805
F2 = ExecRealFunction( ptr % PROCEDURE,CurrentModel, k, T(1) )
5806
dFdx = ( F2 - F1 ) / (2*xeps)
5807
END IF
5808
END IF
5809
CALL ListPopActiveName()
5810
ELSE
5811
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
5812
CALL Fatal( 'ListGetFun', 'Value type for property ['//TRIM(Name)// &
5813
'] not used consistently.')
5814
END IF
5815
F = InterpolateCurve( ptr % TValues,ptr % FValues(1,1,:), &
5816
x, ptr % CubicCoeff )
5817
! Compute the derivative symbolically from the table values.
5818
IF( PRESENT( dFdx ) ) THEN
5819
dFdx = DerivateCurve(ptr % TValues,ptr % FValues(1,1,:), &
5820
x, ptr % CubicCoeff )
5821
END IF
5822
END IF
5823
5824
5825
CASE( LIST_TYPE_VARIABLE_SCALAR_STR )
5826
5827
IF ( .NOT. ptr % LuaFun ) THEN
5828
F = GetMatcReal(ptr % Cvalue,1,[x])
5829
ELSE
5830
CALL ElmerEvalLua(LuaState, ptr, T, F, 1 )
5831
END IF
5832
5833
IF( PRESENT( dFdx ) ) THEN
5834
IF( ASSOCIATED( derPtr ) ) THEN
5835
! Compute also derivative from MATC expression
5836
IF( derPtr % TYPE == LIST_TYPE_VARIABLE_SCALAR_STR ) THEN
5837
IF ( .NOT. derPtr % LuaFun ) THEN
5838
dFdx = GetMatcReal(derptr % Cvalue)
5839
ELSE
5840
CALL ElmerEvalLua(LuaState, derPtr, T, dFdx, 1 )
5841
END IF
5842
ELSE
5843
CALL Fatal('ListGetFun','Derivative should be given the same was as the primary keyword!')
5844
END IF
5845
ELSE
5846
! This is really expensive.
5847
! For speed also one sided difference could be considered.
5848
IF( PRESENT( eps ) ) THEN
5849
xeps = eps
5850
ELSE
5851
xeps = 1.0d-8
5852
END IF
5853
5854
IF ( .NOT. ptr % LuaFun ) THEN
5855
F1 = GetMatcReal(Ptr % Cvalue,1,[x-xeps])
5856
F2 = GetMatcReal(Ptr % Cvalue,1,[x+xeps])
5857
ELSE
5858
T(1) = x-xeps
5859
CALL ElmerEvalLua(LuaState, derPtr, T, F1, 1 )
5860
T(1) = x+xeps
5861
CALL ElmerEvalLua(LuaState, derPtr, T, F2, 1 )
5862
T(1) = x
5863
END IF
5864
dFdx = (F2-F1) / (2*xeps)
5865
END IF
5866
END IF
5867
5868
CASE DEFAULT
5869
CALL Fatal('ListGetFun','LIST_TYPE not implemented!')
5870
5871
END SELECT
5872
5873
IF ( PRESENT( minv ) ) THEN
5874
IF ( F < minv ) THEN
5875
WRITE( Message,*) 'Given value ', F, ' for property: ', '[', TRIM(Name),']', &
5876
' smaller than given minimum: ', minv
5877
CALL Fatal( 'ListGetFun', Message )
5878
END IF
5879
END IF
5880
5881
IF ( PRESENT( maxv ) ) THEN
5882
IF ( F > maxv ) THEN
5883
WRITE( Message,*) 'Given value ', F, ' for property: ', '[', TRIM(Name),']', &
5884
' larger than given maximum ', maxv
5885
CALL Fatal( 'ListGetFun', Message )
5886
END IF
5887
END IF
5888
5889
END FUNCTION ListGetFun
5890
!------------------------------------------------------------------------------
5891
5892
5893
!------------------------------------------------------------------------------
5894
RECURSIVE FUNCTION ListGetFunVec( List,Name,x,dofs,Found,dFdx,eps ) RESULT(F)
5895
!------------------------------------------------------------------------------
5896
TYPE(ValueList_t), POINTER :: List
5897
REAL(KIND=dp), OPTIONAL :: x(*)
5898
INTEGER, OPTIONAL :: dofs
5899
REAL(KIND=dp) :: f
5900
CHARACTER(LEN=*), OPTIONAL :: Name
5901
LOGICAL, OPTIONAL :: Found
5902
REAL(KIND=dp), OPTIONAL :: dFdx(*), eps
5903
!------------------------------------------------------------------------------
5904
TYPE(Variable_t), POINTER :: Variable, CVar, TVar
5905
TYPE(ValueListEntry_t), POINTER :: ptr, prevptr, derptr
5906
REAL(KIND=dp) :: T(10)
5907
INTEGER :: i,j,k,k1,l,l0,l1,lsize
5908
LOGICAL :: GotIt
5909
REAL(KIND=dp) :: xeps, F2, F1
5910
CHARACTER(:), ALLOCATABLE :: tstr
5911
!------------------------------------------------------------------------------
5912
5913
SAVE prevptr, derptr
5914
5915
IF(.NOT. PRESENT(x) ) THEN
5916
CALL Fatal('ListGetFunVec','Variable "x" is in fact compulsory!')
5917
END IF
5918
5919
F = 0.0_dp
5920
IF( PRESENT( Name ) ) THEN
5921
ptr => ListFind(List,Name,Found)
5922
IF ( .NOT.ASSOCIATED(ptr) ) RETURN
5923
ELSE
5924
IF(.NOT.ASSOCIATED(List)) RETURN
5925
ptr => List % Head
5926
IF ( .NOT.ASSOCIATED(ptr) ) THEN
5927
CALL Warn('ListGetFunVec','List entry not associated')
5928
RETURN
5929
END IF
5930
END IF
5931
5932
! Node number not applicable, hence set to zero
5933
k = 0
5934
T(1:dofs) = x(1:dofs)
5935
5936
SELECT CASE(ptr % TYPE)
5937
5938
CASE( LIST_TYPE_VARIABLE_SCALAR )
5939
5940
IF ( ptr % PROCEDURE /= 0 ) THEN
5941
!CALL ListPushActiveName(name)
5942
F = ExecRealFunction( ptr % PROCEDURE,CurrentModel, k, T(1:dofs) )
5943
5944
! Compute derivative at the point if requested
5945
IF( PRESENT( dFdx ) ) THEN
5946
! Numerical central difference scheme is used for accuracy.
5947
IF( PRESENT( eps ) ) THEN
5948
xeps = eps
5949
ELSE
5950
xeps = 1.0d-6
5951
END IF
5952
5953
DO i=1,dofs
5954
T(i) = x(i) - xeps
5955
F1 = ExecRealFunction( ptr % PROCEDURE,CurrentModel, k, T(1:dofs) )
5956
T(i) = x(i) + xeps
5957
F2 = ExecRealFunction( ptr % PROCEDURE,CurrentModel, k, T(1:dofs) )
5958
dFdx(i) = ( F2 - F1 ) / (2*xeps)
5959
T(i) = x(i)
5960
END DO
5961
END IF
5962
!CALL ListPopActiveName()
5963
END IF
5964
5965
5966
CASE( LIST_TYPE_VARIABLE_SCALAR_STR )
5967
IF ( .NOT. ptr % LuaFun ) THEN
5968
F = GetMatcReal(ptr % Cvalue,dofs,T)
5969
ELSE
5970
CALL ElmerEvalLua(LuaState, ptr, T(1:dofs), F, dofs )
5971
END IF
5972
5973
IF( PRESENT( dFdx ) ) THEN
5974
! For speed also one sided difference could be considered.
5975
IF( PRESENT( eps ) ) THEN
5976
xeps = eps
5977
ELSE
5978
xeps = 1.0d-6
5979
END IF
5980
DO i=1,dofs
5981
IF ( .NOT. ptr % LuaFun ) THEN
5982
tstr = 'tx('//I2S(i-1)//')'
5983
F1 = GetMatcReal(ptr % Cvalue,1,[x(i)-xeps],tstr)
5984
F2 = GetMatcReal(ptr % Cvalue,1,[x(i)+xeps],tstr)
5985
5986
! HAS BEEN a NO-OP, NOT CHANGED!!!!!
5987
! ! Revert back to original value
5988
! WRITE( cmd, * ) 'tx('//I2S(i-1)//')=', x(i)
5989
ELSE
5990
T(i) = T(i) - eps
5991
CALL ElmerEvalLua(LuaState, ptr, T(1:dofs), F1, dofs )
5992
T(i) = T(i) + 2*eps
5993
CALL ElmerEvalLua(LuaState, ptr, T(1:dofs), F2, dofs )
5994
T(i) = T(i) - eps
5995
END IF
5996
dFdx(i) = (F2-F1) / (2*xeps)
5997
END DO
5998
END IF
5999
6000
CASE DEFAULT
6001
CALL Fatal('ListGetFunVec','LIST_TYPE not implemented!')
6002
6003
END SELECT
6004
6005
END FUNCTION ListGetFunVec
6006
!------------------------------------------------------------------------------
6007
6008
6009
6010
6011
RECURSIVE SUBROUTINE ListInitHandle( Handle )
6012
6013
TYPE(ValueHandle_t) :: Handle
6014
6015
Handle % ValueType = -1
6016
Handle % SectionType = -1
6017
Handle % ListId = -1
6018
Handle % Element => NULL()
6019
Handle % List => NULL()
6020
Handle % Ptr => NULL()
6021
Handle % Nodes => NULL()
6022
Handle % Indexes => NULL()
6023
Handle % nValuesVec = 0
6024
Handle % ValuesVec => NULL()
6025
Handle % Values => NULL()
6026
Handle % ParValues => NULL()
6027
Handle % ParNo = 0
6028
Handle % DefIValue = 0
6029
Handle % DefRValue = 0.0_dp
6030
Handle % Rdim = 0
6031
Handle % RTensor => NULL()
6032
Handle % RTensorValues => NULL()
6033
Handle % DefLValue = .FALSE.
6034
Handle % Initialized = .FALSE.
6035
Handle % AllocationsDone = .FALSE.
6036
Handle % ConstantEverywhere = .FALSE.
6037
Handle % GlobalEverywhere = .FALSE.
6038
Handle % GlobalInList = .FALSE.
6039
Handle % EvaluateAtIP = .FALSE.
6040
Handle % SomeVarAtIp = .FALSE.
6041
Handle % SomewhereEvaluateAtIP = .FALSE.
6042
Handle % NotPresentAnywhere = .FALSE.
6043
Handle % UnfoundFatal = .FALSE.
6044
Handle % GotMinv = .FALSE.
6045
Handle % GotMaxv = .FALSE.
6046
Handle % VarCount = 0
6047
Handle % HandleIm => NULL()
6048
Handle % Handle2 => NULL()
6049
Handle % Handle3 => NULL()
6050
6051
END SUBROUTINE ListInitHandle
6052
6053
6054
!------------------------------------------------------------------------------
6055
!> Initializes the handle to save just a little bit for constant valued.
6056
!> This is not mandatory but may still be used.
6057
!------------------------------------------------------------------------------
6058
RECURSIVE SUBROUTINE ListInitElementKeyword( Handle,Section,Name,minv,maxv,&
6059
DefRValue,DefIValue,DefLValue,UnfoundFatal,EvaluateAtIp,&
6060
FoundSomewhere,InitIm,InitVec3D,DummyCount)
6061
!------------------------------------------------------------------------------
6062
TYPE(ValueHandle_t) :: Handle
6063
CHARACTER(LEN=*) :: Section,Name
6064
REAL(KIND=dp), OPTIONAL :: minv,maxv
6065
REAL(KIND=dp), OPTIONAL :: DefRValue
6066
INTEGER, OPTIONAL :: DefIValue
6067
LOGICAL, OPTIONAL :: DefLValue
6068
LOGICAL, OPTIONAL :: UnfoundFatal
6069
LOGICAL, OPTIONAL :: EvaluateAtIp
6070
LOGICAL, OPTIONAL :: FoundSomewhere
6071
LOGICAL, OPTIONAL :: InitIm
6072
LOGICAL, OPTIONAL :: InitVec3D
6073
INTEGER, OPTIONAL :: DummyCount
6074
!------------------------------------------------------------------------------
6075
TYPE(ValueList_t), POINTER :: List
6076
TYPE(ValueListEntry_t), POINTER :: ptr
6077
INTEGER :: i, ni, NoVal, ValueType, IValue, dim, n, m, maxn, maxm
6078
TYPE(Model_t), POINTER :: Model
6079
REAL(KIND=dp) :: val, Rvalue
6080
CHARACTER(:), ALLOCATABLE :: CValue
6081
LOGICAL :: ConstantEverywhere, NotPresentAnywhere, Lvalue, FirstList, AllGlobal, Found
6082
REAL(KIND=dp), POINTER :: Basis(:)
6083
INTEGER, POINTER :: NodeIndexes(:)
6084
TYPE(Element_t), POINTER :: Element
6085
LOGICAL :: GotIt, FoundSomewhere1, FoundSomewhere2
6086
!------------------------------------------------------------------------------
6087
6088
! Number of internal variables that should be present on all function calls
6089
IF( PRESENT( DummyCount ) ) THEN
6090
Handle % IntVarCount = DummyCount
6091
END IF
6092
6093
IF( PRESENT( InitIm ) ) THEN
6094
IF( InitIm ) THEN
6095
IF( .NOT. ASSOCIATED( Handle % HandleIm ) ) THEN
6096
ALLOCATE( Handle % HandleIm )
6097
CALL ListInitHandle( Handle % HandleIm )
6098
END IF
6099
CALL Info('ListInitElementKeyword','Treating real part of keyword',Level=15)
6100
CALL ListInitElementKeyword( Handle,Section,Name,minv,maxv,&
6101
DefRValue,DefIValue,DefLValue,UnfoundFatal,EvaluateAtIp,FoundSomewhere,InitVec3D=InitVec3D)
6102
IF( PRESENT( FoundSomewhere) ) FoundSomewhere1 = FoundSomewhere
6103
6104
CALL Info('ListInitElementKeyword','Treating imaginary part of keyword',Level=15)
6105
CALL ListInitElementKeyword( Handle % HandleIm,Section,TRIM(Name)//' im',minv,maxv,&
6106
DefRValue,DefIValue,DefLValue,UnfoundFatal,EvaluateAtIp,FoundSomewhere,InitVec3D=InitVec3D)
6107
IF( PRESENT( FoundSomewhere ) ) FoundSomewhere = FoundSomewhere .OR. FoundSomewhere1
6108
RETURN
6109
END IF
6110
END IF
6111
6112
IF( PRESENT( InitVec3D ) ) THEN
6113
IF( InitVec3D ) THEN
6114
IF( .NOT. ASSOCIATED( Handle % Handle2 ) ) THEN
6115
ALLOCATE( Handle % Handle2 )
6116
CALL ListInitHandle( Handle % Handle2 )
6117
END IF
6118
IF( .NOT. ASSOCIATED( Handle % Handle3 ) ) THEN
6119
ALLOCATE( Handle % Handle3 )
6120
CALL ListInitHandle( Handle % Handle3 )
6121
END IF
6122
6123
CALL ListInitElementKeyword( Handle,Section,TRIM(Name)//' 1',minv,maxv,&
6124
DefRValue,DefIValue,DefLValue,UnfoundFatal,EvaluateAtIp,FoundSomewhere)
6125
IF( PRESENT( FoundSomewhere) ) FoundSomewhere1 = FoundSomewhere
6126
CALL ListInitElementKeyword( Handle % Handle2,Section,TRIM(Name)//' 2',minv,maxv,&
6127
DefRValue,DefIValue,DefLValue,UnfoundFatal,EvaluateAtIp,FoundSomewhere)
6128
IF( PRESENT( FoundSomewhere) ) FoundSomewhere2 = FoundSomewhere
6129
CALL ListInitElementKeyword( Handle % Handle3,Section,TRIM(Name)//' 3',minv,maxv,&
6130
DefRValue,DefIValue,DefLValue,UnfoundFatal,EvaluateAtIp,FoundSomewhere)
6131
IF( PRESENT( FoundSomewhere ) ) FoundSomewhere = FoundSomewhere .OR. &
6132
FoundSomewhere1 .OR. FoundSomewhere2
6133
RETURN
6134
END IF
6135
END IF
6136
6137
CALL Info('ListInitElementKeyword','Treating keyword: '//TRIM(Name),Level=12)
6138
6139
Model => CurrentModel
6140
Handle % BulkElement = .TRUE.
6141
NULLIFY(ptr)
6142
6143
SELECT CASE ( Section )
6144
6145
CASE('Body')
6146
Handle % SectionType = SECTION_TYPE_BODY
6147
6148
CASE('Material')
6149
Handle % SectionType = SECTION_TYPE_MATERIAL
6150
6151
CASE('Body Force')
6152
Handle % SectionType = SECTION_TYPE_BF
6153
6154
CASE('Initial Condition')
6155
Handle % SectionType = SECTION_TYPE_IC
6156
6157
CASE('Boundary Condition')
6158
Handle % SectionType = SECTION_TYPE_BC
6159
Handle % BulkElement = .FALSE.
6160
6161
CASE('Component')
6162
Handle % SectionType = SECTION_TYPE_COMPONENT
6163
6164
CASE('Equation')
6165
Handle % SectionType = SECTION_TYPE_EQUATION
6166
6167
CASE DEFAULT
6168
CALL Fatal('ListInitElementKeyword','Unknown section: '//TRIM(Section))
6169
6170
END SELECT
6171
6172
6173
! Initialize the handle entries because it may be that the list structure was altered,
6174
! or the same handle is used for different keyword.
6175
Handle % ConstantEverywhere = .TRUE.
6176
Handle % GlobalInList = .FALSE.
6177
Handle % NotPresentAnywhere = .TRUE.
6178
Handle % SomewhereEvaluateAtIP = .FALSE.
6179
Handle % GlobalEverywhere = .TRUE.
6180
Handle % SomeVarAtIp = .FALSE.
6181
Handle % Name = TRIM(Name)
6182
Handle % ListId = -1
6183
Handle % EvaluateAtIp = .FALSE.
6184
Handle % List => NULL()
6185
Handle % Element => NULL()
6186
Handle % Unfoundfatal = .FALSE.
6187
IF (.NOT. ASSOCIATED( Handle % Ptr ) ) THEN
6188
Handle % Ptr => ListAllocate()
6189
END IF
6190
6191
6192
! Deallocate stuff that may change in size, or is used as a marker for first element
6193
IF( Handle % nValuesVec > 0 ) THEN
6194
DEALLOCATE( Handle % ValuesVec )
6195
Handle % nValuesVec = 0
6196
END IF
6197
6198
6199
Handle % Initialized = .TRUE.
6200
6201
FirstList = .TRUE.
6202
maxn = 0
6203
maxm = 0
6204
6205
i = 0
6206
DO WHILE(.TRUE.)
6207
i = i + 1
6208
6209
SELECT CASE ( Handle % SectionType )
6210
6211
CASE( SECTION_TYPE_BODY )
6212
IF(i > Model % NumberOfBodies ) EXIT
6213
List => Model % Bodies(i) % Values
6214
6215
CASE( SECTION_TYPE_MATERIAL )
6216
IF(i > Model % NumberOfMaterials ) EXIT
6217
List => Model % Materials(i) % Values
6218
6219
CASE( SECTION_TYPE_BF )
6220
IF(i > Model % NumberOfBodyForces ) EXIT
6221
List => Model % BodyForces(i) % Values
6222
6223
CASE( SECTION_TYPE_IC )
6224
IF( i > Model % NumberOfICs ) EXIT
6225
List => Model % ICs(i) % Values
6226
6227
CASE( SECTION_TYPE_EQUATION )
6228
IF( i > Model % NumberOfEquations ) EXIT
6229
List => Model % Equations(i) % Values
6230
6231
CASE( SECTION_TYPE_COMPONENT )
6232
IF( i > Model % NumberOfComponents ) EXIT
6233
List => Model % Components(i) % Values
6234
6235
CASE( SECTION_TYPE_BC )
6236
IF( i > Model % NumberOfBCs ) EXIT
6237
List => Model % BCs(i) % Values
6238
6239
! It is more difficult to make sure that the BC list is given for all BC elements.
6240
! Therefore set this to .FALSE. always for BCs.
6241
Handle % ConstantEverywhere = .FALSE.
6242
6243
CASE DEFAULT
6244
CALL Fatal('ListInitElementKeyword','Unknown section: '//I2S(Handle % SectionType))
6245
6246
END SELECT
6247
6248
! If the parameter is not defined in some list we cannot really be sure
6249
! that it is intentionally used as a zero. Hence we cannot assume that the
6250
! keyword is constant.
6251
ptr => ListFind(List,Name,Found)
6252
Handle % ptr % Head => ptr
6253
6254
IF ( .NOT. ASSOCIATED(ptr) ) THEN
6255
Handle % ConstantEverywhere = .FALSE.
6256
CYCLE
6257
ELSE IF( FirstList ) THEN
6258
Handle % NotPresentAnywhere = .FALSE.
6259
Handle % ValueType = ptr % Type
6260
END IF
6261
6262
ValueType = ptr % TYPE
6263
6264
IF( ValueType == LIST_TYPE_LOGICAL ) THEN
6265
Lvalue = ptr % Lvalue
6266
6267
IF( FirstList ) THEN
6268
Handle % LValue = LValue
6269
ELSE
6270
IF( Handle % LValue .NEQV. LValue ) THEN
6271
Handle % ConstantEverywhere = .FALSE.
6272
EXIT
6273
END IF
6274
END IF
6275
6276
ELSE IF( ValueType == LIST_TYPE_STRING ) THEN
6277
Cvalue = ptr % Cvalue
6278
IF( FirstList ) THEN
6279
Handle % CValueLen = len_trim(CValue)
6280
Handle % CValue = CValue(1:Handle % CValueLen)
6281
ELSE IF( Handle % CValue(1:Handle % CValueLen) /= Cvalue ) THEN
6282
Handle % ConstantEverywhere = .FALSE.
6283
EXIT
6284
END IF
6285
6286
ELSE IF( ValueType == LIST_TYPE_INTEGER ) THEN
6287
Ivalue = ptr % Ivalues(1)
6288
IF( FirstList ) THEN
6289
Handle % IValue = Ivalue
6290
ELSE IF( Handle % IValue /= Ivalue ) THEN
6291
Handle % ConstantEverywhere = .FALSE.
6292
EXIT
6293
END IF
6294
6295
ELSE IF( ValueType >= LIST_TYPE_CONSTANT_SCALAR .AND. &
6296
ValueType <= List_TYPE_CONSTANT_SCALAR_PROC ) THEN
6297
6298
IF( PRESENT( DummyCount ) ) THEN
6299
! If we feed internal variables then the evaluation cannot be global
6300
AllGlobal = .FALSE.
6301
ELSE
6302
! If the matc depends on only global variable, like time, we know that the values
6303
! of the MATC functions will be constant for each list.
6304
AllGlobal = ListCheckAllGlobal( Handle % ptr, name )
6305
END IF
6306
IF(.NOT. AllGlobal ) THEN
6307
Handle % GlobalEverywhere = .FALSE.
6308
Handle % ConstantEverywhere = .FALSE.
6309
IF( ListGetLogical( List, TRIM( Handle % Name )//' At IP',GotIt ) ) THEN
6310
Handle % SomewhereEvaluateAtIp = .TRUE.
6311
EXIT
6312
END IF
6313
END IF
6314
6315
IF( Handle % ConstantEverywhere ) THEN
6316
Rvalue = ListGetCReal( List,Name)
6317
! and each list must have the same constant value
6318
IF( FirstList ) THEN
6319
Handle % RValue = Rvalue
6320
ELSE IF( ABS( Handle % RValue - Rvalue ) > TINY( RValue ) ) THEN
6321
Handle % ConstantEverywhere = .FALSE.
6322
END IF
6323
END IF
6324
6325
ELSE IF( ValueType >= LIST_TYPE_CONSTANT_TENSOR .AND. &
6326
ValueType <= LIST_TYPE_VARIABLE_TENSOR_STR ) THEN
6327
6328
Handle % GlobalEverywhere = .FALSE.
6329
Handle % ConstantEverywhere = .FALSE.
6330
IF( ListGetLogical( List, TRIM( Handle % Name )//' At IP',GotIt ) ) THEN
6331
Handle % SomewhereEvaluateAtIp = .TRUE.
6332
END IF
6333
6334
n = SIZE( ptr % FValues,1 )
6335
m = SIZE( ptr % FValues,2 )
6336
maxn = MAX( n, maxn )
6337
maxm = MAX( m, maxm )
6338
ELSE
6339
CALL Fatal('ListInitElementKeyword','Unknown value type: '//I2S(ValueType))
6340
6341
END IF
6342
6343
FirstList = .FALSE.
6344
END DO
6345
6346
CALL Info('ListInitElementKeyword',&
6347
'Initiated handle for: > '//TRIM(Handle % Name)//' < of type: '// &
6348
I2S(Handle % ValueType),Level=12)
6349
6350
IF( PRESENT( UnfoundFatal ) ) THEN
6351
Handle % Unfoundfatal = UnfoundFatal
6352
IF( Handle % UnfoundFatal .AND. Handle % NotPresentAnywhere ) THEN
6353
CALL Fatal('ListInitElementKeywords','Keyword required but not present: '&
6354
//TRIM(Handle % Name))
6355
END IF
6356
END IF
6357
6358
IF( PRESENT( DefLValue ) ) THEN
6359
Handle % DefLValue = DefLValue
6360
END IF
6361
6362
IF( PRESENT( DefRValue ) ) THEN
6363
Handle % DefRValue = DefRValue
6364
END IF
6365
6366
IF( PRESENT( DefIValue ) ) THEN
6367
Handle % DefIValue = DefIValue
6368
END IF
6369
6370
IF( PRESENT( minv ) ) THEN
6371
Handle % GotMinv = .TRUE.
6372
Handle % minv = minv
6373
END IF
6374
6375
IF( PRESENT( maxv ) ) THEN
6376
Handle % GotMaxv = .TRUE.
6377
Handle % maxv = maxv
6378
END IF
6379
6380
IF( PRESENT( EvaluateAtIp ) ) THEN
6381
Handle % EvaluateAtIp = EvaluateAtIp
6382
END IF
6383
6384
IF( PRESENT( FoundSomewhere ) ) THEN
6385
FoundSomewhere = .NOT. Handle % NotPresentAnywhere
6386
END IF
6387
6388
! For tensor valued ListGetRealElement operations allocate the maximum size
6389
! of temporal table needed.
6390
IF( maxn > 1 .OR. maxm > 1 ) THEN
6391
ni = CurrentModel % Mesh % MaxElementNodes
6392
IF( ASSOCIATED( Handle % RtensorValues ) ) THEN
6393
IF( SIZE( Handle % RtensorValues, 1 ) < maxn .OR. &
6394
SIZE( Handle % RtensorValues, 2 ) < maxm .OR. &
6395
SIZE( Handle % RtensorValues, 3 ) < ni ) THEN
6396
DEALLOCATE( Handle % RtensorValues )
6397
END IF
6398
END IF
6399
IF(.NOT. ASSOCIATED( Handle % RtensorValues ) ) THEN
6400
ALLOCATE( Handle % RtensorValues(maxn,maxm,ni) )
6401
END IF
6402
END IF
6403
6404
END SUBROUTINE ListInitElementKeyword
6405
!------------------------------------------------------------------------------
6406
6407
6408
6409
!------------------------------------------------------------------------------
6410
!> Given a pointer to the element and the correct handle for the keyword find
6411
!> the list where the keyword valued should be found in.
6412
!------------------------------------------------------------------------------
6413
FUNCTION ElementHandleList( Element, Handle, ListSame, ListFound ) RESULT( List )
6414
6415
TYPE(Element_t), POINTER :: Element
6416
TYPE(ValueHandle_t) :: Handle
6417
TYPE(ValueList_t), POINTER :: List
6418
LOGICAL :: ListSame, ListFound
6419
!------------------------------------------------------------------------------
6420
INTEGER :: ListId, id
6421
6422
List => NULL()
6423
6424
ListSame = .FALSE.
6425
ListFound = .FALSE.
6426
6427
6428
! We are looking for the same element as previous time
6429
IF( ASSOCIATED( Element, Handle % Element ) ) THEN
6430
ListSame = .TRUE.
6431
List => Handle % List
6432
RETURN
6433
END IF
6434
6435
! Ok, not the same element, get the index that determines the list
6436
IF( Handle % BulkElement ) THEN
6437
ListId = Element % BodyId
6438
ELSE
6439
ListId = 0
6440
IF( ASSOCIATED( Element % BoundaryInfo ) ) THEN
6441
ListId = Element % BoundaryInfo % Constraint
6442
END IF
6443
END IF
6444
6445
! We are looking at the same list as previous time
6446
IF( Handle % ListId == ListId ) THEN
6447
ListSame = .TRUE.
6448
List => Handle % List
6449
RETURN
6450
ELSE
6451
Handle % ListId = ListId
6452
IF( ListId <= 0 ) RETURN
6453
END IF
6454
6455
! Ok, we cannot use previous list, lets find the new list
6456
SELECT CASE ( Handle % SectionType )
6457
6458
CASE( SECTION_TYPE_BODY )
6459
List => CurrentModel % Bodies(ListId) % Values
6460
ListFound = .TRUE.
6461
6462
CASE( SECTION_TYPE_BF )
6463
id = ListGetInteger( CurrentModel % Bodies(ListId) % Values, &
6464
'Body Force', ListFound )
6465
IF( ListFound ) List => CurrentModel % BodyForces(id) % Values
6466
6467
CASE( SECTION_TYPE_IC )
6468
id = ListGetInteger( CurrentModel % Bodies(ListId) % Values, &
6469
'Initial Condition', ListFound )
6470
IF(ListFound) List => CurrentModel % ICs(id) % Values
6471
6472
CASE( SECTION_TYPE_MATERIAL )
6473
IF( ASSOCIATED( Element % BoundaryInfo ) ) THEN
6474
id = Element % BoundaryInfo % Constraint
6475
IF(id >= 1 .AND. id <= CurrentModel % NumberOfBCs ) THEN
6476
id = ListGetInteger( CurrentModel % BCs(id) % Values, &
6477
'Material', ListFound )
6478
ELSE
6479
id = 0
6480
END IF
6481
ELSE
6482
id = ListGetInteger( CurrentModel % Bodies(ListId) % Values, &
6483
'Material', ListFound )
6484
END IF
6485
IF(ListFound) List => CurrentModel % Materials(id) % Values
6486
6487
CASE( SECTION_TYPE_COMPONENT )
6488
id = ListGetInteger( CurrentModel % Bodies(ListId) % Values, &
6489
'Component', ListFound )
6490
IF(ListFound) List => CurrentModel % Components(id) % Values
6491
6492
CASE( SECTION_TYPE_EQUATION )
6493
id = ListGetInteger( CurrentModel % Bodies(ListId) % Values, &
6494
'Equation', ListFound )
6495
IF(ListFound) List => CurrentModel % Equations(id) % Values
6496
6497
CASE( SECTION_TYPE_BC )
6498
IF( ListId <= 0 .OR. ListId > CurrentModel % NumberOfBCs ) RETURN
6499
IF( CurrentModel % BCs(ListId) % Tag == ListId ) THEN
6500
List => CurrentModel % BCs(ListId) % Values
6501
ListFound = .TRUE.
6502
END IF
6503
6504
CASE( -1 )
6505
CALL Fatal('ElementHandleList','Handle not initialized!')
6506
6507
CASE DEFAULT
6508
CALL Fatal('ElementHandleList','Unknown section type!')
6509
6510
END SELECT
6511
6512
IF( ListFound ) THEN
6513
! We still have chance that this is the same list
6514
IF( ASSOCIATED( List, Handle % List ) ) THEN
6515
ListSame = .TRUE.
6516
ELSE
6517
Handle % List => List
6518
END IF
6519
ELSE
6520
Handle % List => NULL()
6521
END IF
6522
6523
END FUNCTION ElementHandleList
6524
!------------------------------------------------------------------------------
6525
6526
!------------------------------------------------------------------------------
6527
!> Given an index related to the related to the correct section returns the correct
6528
!> value list and a logical flag if there are no more.
6529
!------------------------------------------------------------------------------
6530
FUNCTION SectionHandleList( Handle, ListId, EndLoop ) RESULT( List )
6531
6532
TYPE(ValueHandle_t) :: Handle
6533
TYPE(ValueList_t), POINTER :: List
6534
INTEGER :: ListId
6535
LOGICAL :: EndLoop
6536
!------------------------------------------------------------------------------
6537
LOGICAL :: Found
6538
INTEGER :: id
6539
6540
List => NULL()
6541
6542
IF( Handle % SectionType == SECTION_TYPE_BC ) THEN
6543
EndLoop = ( ListId <= 0 .OR. ListId > CurrentModel % NumberOfBCs )
6544
ELSE
6545
EndLoop = ( ListId > CurrentModel % NumberOfBodies )
6546
END IF
6547
IF( EndLoop ) RETURN
6548
6549
6550
SELECT CASE ( Handle % SectionType )
6551
6552
CASE( SECTION_TYPE_BODY )
6553
List => CurrentModel % Bodies(ListId) % Values
6554
6555
CASE( SECTION_TYPE_BF )
6556
id = ListGetInteger( CurrentModel % Bodies(ListId) % Values, &
6557
'Body Force', Found )
6558
IF( Found ) List => CurrentModel % BodyForces(id) % Values
6559
6560
CASE( SECTION_TYPE_IC )
6561
id = ListGetInteger( CurrentModel % Bodies(ListId) % Values, &
6562
'Initial Condition', Found )
6563
IF(Found) List => CurrentModel % ICs(id) % Values
6564
6565
CASE( SECTION_TYPE_MATERIAL )
6566
id = ListGetInteger( CurrentModel % Bodies(ListId) % Values, &
6567
'Material', Found )
6568
IF(Found) List => CurrentModel % Materials(id) % Values
6569
6570
CASE( SECTION_TYPE_EQUATION )
6571
id = ListGetInteger( CurrentModel % Bodies(ListId) % Values, &
6572
'Equation',Found )
6573
IF(Found) List => CurrentModel % Equations(id) % Values
6574
6575
CASE( SECTION_TYPE_BC )
6576
List => CurrentModel % BCs(ListId) % Values
6577
6578
CASE( -1 )
6579
CALL Fatal('SectionHandleList','Handle not initialized!')
6580
6581
CASE DEFAULT
6582
CALL Fatal('SectionHandleList','Unknown section type!')
6583
6584
END SELECT
6585
6586
END FUNCTION SectionHandleList
6587
!------------------------------------------------------------------------------
6588
6589
6590
6591
!------------------------------------------------------------------------------
6592
!> Compares a string valued parameter in elements and return True if they are the same.
6593
!------------------------------------------------------------------------------
6594
FUNCTION ListCompareElementAnyString( Handle, RefValue ) RESULT( Same )
6595
!------------------------------------------------------------------------------
6596
TYPE(ValueHandle_t) :: Handle
6597
CHARACTER(LEN=*) :: RefValue
6598
LOGICAL :: Same
6599
!------------------------------------------------------------------------------
6600
TYPE(ValueList_t), POINTER :: List
6601
LOGICAL :: Found, EndLoop
6602
INTEGER :: id, n
6603
CHARACTER(:), ALLOCATABLE :: ThisValue
6604
!------------------------------------------------------------------------------
6605
6606
Same = .FALSE.
6607
6608
! If value is not present anywhere then return False
6609
IF( Handle % NotPresentAnywhere ) RETURN
6610
6611
id = 0
6612
DO WHILE (.TRUE.)
6613
id = id + 1
6614
List => SectionHandleList( Handle, id, EndLoop )
6615
IF( EndLoop ) EXIT
6616
IF(.NOT. ASSOCIATED( List ) ) CYCLE
6617
6618
ThisValue = ListGetString( List, Handle % Name, Found )
6619
IF( Found ) THEN
6620
n = len_TRIM(ThisValue)
6621
Same = ( ThisValue(1:n) == RefValue )
6622
IF( Same ) EXIT
6623
END IF
6624
END DO
6625
6626
END FUNCTION ListCompareElementAnyString
6627
!------------------------------------------------------------------------------
6628
6629
6630
!------------------------------------------------------------------------------
6631
!> Checks whether any of the logical flags has the desired logical value.
6632
!------------------------------------------------------------------------------
6633
FUNCTION ListCompareElementAnyLogical( Handle, RefValue ) RESULT( Same )
6634
!------------------------------------------------------------------------------
6635
TYPE(ValueHandle_t) :: Handle
6636
LOGICAL :: RefValue
6637
LOGICAL :: Same
6638
!------------------------------------------------------------------------------
6639
LOGICAL :: ThisValue
6640
TYPE(ValueList_t), POINTER :: List
6641
LOGICAL :: Found, EndLoop
6642
INTEGER :: id, CValueLen
6643
!------------------------------------------------------------------------------
6644
6645
Same = .FALSE.
6646
6647
! If value is not present anywhere then return False
6648
IF( Handle % NotPresentAnywhere ) RETURN
6649
6650
id = 0
6651
DO WHILE (.TRUE.)
6652
id = id + 1
6653
List => SectionHandleList( Handle, id, EndLoop )
6654
IF( EndLoop ) EXIT
6655
IF(.NOT. ASSOCIATED( List ) ) CYCLE
6656
6657
ThisValue = ListGetLogical( List, Handle % Name, Found )
6658
IF( Found ) THEN
6659
IF( ThisValue .AND. RefValue ) THEN
6660
Same = .TRUE.
6661
ELSE IF(.NOT. ThisValue .AND. .NOT. RefValue ) THEN
6662
Same = .TRUE.
6663
END IF
6664
IF( Same ) EXIT
6665
END IF
6666
END DO
6667
6668
END FUNCTION ListCompareElementAnyLogical
6669
!------------------------------------------------------------------------------
6670
6671
6672
6673
6674
!------------------------------------------------------------------------------
6675
!> Get value of parameter from either of the parents.
6676
!> If the value is found then the Left/Right parent is memorized internally.
6677
!> Might not be economical if there are two keywords that toggle but usually
6678
!> we just fetch one keyword from the parents.
6679
!------------------------------------------------------------------------------
6680
FUNCTION ListGetElementRealParent( Handle, Basis, Element, Found ) RESULT( RValue )
6681
6682
TYPE(ValueHandle_t) :: Handle
6683
TYPE(Element_t), OPTIONAL, POINTER :: Element
6684
REAL(KIND=dp), OPTIONAL :: Basis(:)
6685
LOGICAL, OPTIONAL :: Found
6686
REAL(KIND=dp) :: RValue
6687
LOGICAL :: IntFound
6688
LOGICAL :: lefttest = .TRUE. ! first start with left test 1st
6689
TYPE(Element_t), POINTER :: Parent, PElement
6690
6691
SAVE lefttest
6692
6693
!$omp threadprivate(lefttest)
6694
6695
! Find the pointer to the element, if not given
6696
IF( PRESENT( Element ) ) THEN
6697
PElement => Element
6698
ELSE
6699
PElement => CurrentModel % CurrentElement
6700
END IF
6701
6702
IntFound = .FALSE.
6703
IF( lefttest) THEN
6704
Parent => PElement % BoundaryInfo % Left
6705
ELSE
6706
Parent => PElement % BoundaryInfo % Right
6707
END IF
6708
6709
RValue = ListGetElementReal( Handle, Basis, Parent, IntFound, PElement % NodeIndexes )
6710
6711
! If not found do the same thing with the other parent
6712
IF(.NOT. IntFound ) THEN
6713
IF( lefttest) THEN
6714
Parent => PElement % BoundaryInfo % Right
6715
ELSE
6716
Parent => PElement % BoundaryInfo % Left
6717
END IF
6718
RValue = ListGetElementReal( Handle, Basis, Parent, IntFound, PElement % NodeIndexes )
6719
6720
! reverse the order in which left and right parent are tested
6721
IF( IntFound ) lefttest = .NOT. lefttest
6722
END IF
6723
6724
IF( PRESENT( Found ) ) Found = IntFound
6725
6726
END FUNCTION ListGetElementRealParent
6727
6728
6729
!------------------------------------------------------------------------------
6730
!> Gets a real valued parameter in the Gaussian integration point defined
6731
!> by the local basis function. To speed up things there is a handle associated
6732
!> to the given keyword (Name). Here the values are first evaluated at the
6733
!> nodal points and then using basis functions estimated at the
6734
!> gaussian integration points.
6735
!------------------------------------------------------------------------------
6736
FUNCTION ListGetElementReal( Handle,Basis,Element,Found,Indexes,&
6737
GaussPoint,Rdim,Rtensor,DummyVals,tstep) RESULT(Rvalue)
6738
!------------------------------------------------------------------------------
6739
TYPE(ValueHandle_t) :: Handle
6740
REAL(KIND=dp), OPTIONAL :: Basis(:)
6741
LOGICAL, OPTIONAL :: Found
6742
TYPE(Element_t), POINTER, OPTIONAL :: Element
6743
INTEGER, POINTER, OPTIONAL :: Indexes(:)
6744
INTEGER, OPTIONAL :: GaussPoint
6745
INTEGER, OPTIONAL :: Rdim
6746
REAL(KIND=dp), POINTER, OPTIONAL :: Rtensor(:,:)
6747
REAL(KIND=dp), OPTIONAL :: DummyVals(:)
6748
INTEGER, OPTIONAL :: tstep
6749
REAL(KIND=dp) :: Rvalue
6750
!------------------------------------------------------------------------------
6751
TYPE(ValueList_t), POINTER :: List
6752
TYPE(Variable_t), POINTER :: Variable, CVar, TVar
6753
TYPE(ValueListEntry_t), POINTER :: ptr
6754
INTEGER, POINTER :: NodeIndexes(:)
6755
REAL(KIND=dp) :: T(MAX_FNC),x,y,z
6756
REAL(KIND=dp), POINTER :: F(:)
6757
REAL(KIND=dp), POINTER :: ParF(:,:)
6758
INTEGER :: i,j,j0,k,j2,k2,k1,l,l0,l1,lsize,ni,bodyid,id,n,m
6759
LOGICAL :: AllGlobal, SomeAtIp, SomeAtNodes, ListSame, ListFound, GotIt, IntFound, &
6760
ElementSame
6761
TYPE(Element_t), POINTER :: PElement
6762
INTEGER :: lstat
6763
!------------------------------------------------------------------------------
6764
6765
! If value is not present anywhere then return False
6766
IF( Handle % NotPresentAnywhere ) THEN
6767
IF(PRESENT(Found)) Found = .FALSE.
6768
Rvalue = Handle % DefRValue
6769
RETURN
6770
END IF
6771
6772
IF( PRESENT( Rdim ) ) Rdim = 0
6773
6774
! If the value is known to be globally constant return it asap.
6775
IF( Handle % ConstantEverywhere ) THEN
6776
IF(PRESENT(Found)) Found = .TRUE.
6777
RValue = Handle % RValue
6778
RETURN
6779
END IF
6780
6781
! Find the pointer to the element, if not given
6782
IF( PRESENT( Element ) ) THEN
6783
PElement => Element
6784
ELSE
6785
PElement => CurrentModel % CurrentElement
6786
END IF
6787
6788
6789
! Set the default value
6790
Rvalue = Handle % DefRValue
6791
ElementSame = .FALSE.
6792
6793
6794
! We know by initialization the list entry type that the keyword has
6795
! Find the correct list to look the keyword in.
6796
! Bulk and boundary elements are treated separately.
6797
List => ElementHandleList( PElement, Handle, ListSame, ListFound )
6798
6799
! If the provided list is the same as last time, also the keyword will
6800
! be sitting at the same place, otherwise find it in the new list
6801
IF( ListSame ) THEN
6802
IF( PRESENT( Found ) ) Found = Handle % Found
6803
IF( .NOT. Handle % Found ) RETURN
6804
6805
IF( Handle % GlobalInList ) THEN
6806
IF( Handle % Rdim == 0 ) THEN
6807
Rvalue = Handle % Values(1)
6808
RETURN
6809
ELSE
6810
! These have been checked already so they should exist
6811
Rdim = Handle % Rdim
6812
Rtensor => Handle % Rtensor
6813
RETURN
6814
END IF
6815
ELSE
6816
ptr => Handle % ptr % head
6817
IF (PRESENT(Rdim) .AND. PRESENT(Rtensor)) THEN
6818
Rdim = Handle % Rdim
6819
Rtensor => Handle % Rtensor
6820
END IF
6821
END IF
6822
ELSE IF( ListFound ) THEN
6823
6824
ptr => ListFind(List,Handle % Name,IntFound )
6825
IF(PRESENT(Found)) Found = IntFound
6826
Handle % Found = IntFound
6827
IF(.NOT. IntFound ) THEN
6828
IF( Handle % UnfoundFatal ) THEN
6829
CALL Fatal('ListGetElementReal','Could not find required keyword in list: '//TRIM(Handle % Name))
6830
END IF
6831
RETURN
6832
END IF
6833
6834
Handle % Ptr % Head => ptr
6835
Handle % Rdim = ptr % Fdim
6836
6837
IF( ptr % Fdim > 0 ) THEN
6838
n = SIZE(ptr % FValues,1)
6839
m = SIZE(ptr % FValues,2)
6840
IF ( ASSOCIATED( Handle % Rtensor) ) THEN
6841
IF ( SIZE(Handle % Rtensor,1) /= n .OR. SIZE(Handle % Rtensor,2) /= m ) THEN
6842
DEALLOCATE( Handle % Rtensor )
6843
END IF
6844
END IF
6845
IF(.NOT. ASSOCIATED( Handle % Rtensor) ) THEN
6846
ALLOCATE( Handle % Rtensor(n,m) )
6847
END IF
6848
6849
IF( PRESENT( Rdim ) .AND. PRESENT( Rtensor ) ) THEN
6850
Rdim = Handle % Rdim
6851
Rtensor => Handle % Rtensor
6852
ELSE
6853
CALL Fatal('ListGetElementReal','For tensors Rdim and Rtensor should be present!')
6854
END IF
6855
END IF
6856
6857
! It does not make sense to evaluate global variables at IP
6858
IF( Handle % SomewhereEvaluateAtIp ) THEN
6859
! Check whether the keyword should be evaluated at integration point directly
6860
! Only these dependency type may depend on position
6861
IF( ptr % TYPE == LIST_TYPE_VARIABLE_SCALAR .OR. &
6862
ptr % TYPE == LIST_TYPE_VARIABLE_SCALAR_STR .OR. &
6863
ptr % TYPE == LIST_TYPE_CONSTANT_SCALAR_PROC ) THEN
6864
Handle % EvaluateAtIP = ListGetLogical( List, TRIM( Handle % Name )//' At IP',GotIt )
6865
ELSE
6866
Handle % EvaluateAtIp = .FALSE.
6867
END IF
6868
END IF
6869
6870
IF( Ptr % DepNameLen > 0 ) THEN
6871
CALL ListParseStrToVars( Ptr % DependName, Ptr % DepNameLen, &
6872
Handle % Name, Handle % VarCount, Handle % VarTable, &
6873
SomeAtIp, SomeAtNodes, AllGlobal, Handle % IntVarCount, List )
6874
6875
Handle % GlobalInList = ( AllGlobal .AND. ptr % PROCEDURE == 0 )
6876
6877
! If some input parameter is given at integration point
6878
! we don't have any option other than evaluate things on IPs
6879
IF( SomeAtIP ) Handle % EvaluateAtIp = .TRUE.
6880
Handle % SomeVarAtIp = SomeAtIp
6881
6882
! If all variables are global ondes we don't need to evaluate things on IPs
6883
IF( AllGlobal ) Handle % EvaluateAtIp = .FALSE.
6884
6885
ELSE
6886
Handle % GlobalInList = ( ptr % PROCEDURE == 0 )
6887
END IF
6888
ELSE
6889
IF( Handle % UnfoundFatal ) THEN
6890
CALL Fatal('ListGetElementReal','Could not find list for required keyword: '//TRIM(Handle % Name))
6891
END IF
6892
Rvalue = Handle % DefRValue
6893
6894
!Handle % Values(1) = RValue
6895
IF( PRESENT(Found) ) THEN
6896
Found = .FALSE.
6897
Handle % Found = .FALSE.
6898
END IF
6899
RETURN
6900
END IF
6901
6902
! This is a later addition by which we add internal variables to be dummy arguments in the
6903
! list when calling Real valued keywords. The number of internal keywords is set on the
6904
! initialization phase of the handle and it is fixed per handle. The hope is that we can
6905
! pass internally computed stuff to the user defined subroutines beyond the typical
6906
! use of existing fields. For example, we can internally compute normal velocity, magnetic
6907
! field, strain velocity etc. This is almost never used.
6908
!------------------------------------------------------------------------------------------
6909
IF( Handle % IntVarCount > 0 ) THEN
6910
IF(.NOT. PRESENT( DummyVals ) ) THEN
6911
CALL Fatal('ListGetElementReal','This handle expects '&
6912
//I2S(Handle % IntVarCount)//' internal variables: '//TRIM(Handle % Name))
6913
END IF
6914
IF( SIZE( DummyVals ) /= Handle % IntVarCount ) THEN
6915
CALL Fatal('ListGetElementReal','We are expecting '&
6916
//I2S(Handle % IntVarCount)//' internal variables: '//TRIM(Handle % Name))
6917
END IF
6918
!Handle % VarTable(1:Handle % IntVarCount) % ParamValue = DummyVals
6919
END IF
6920
6921
6922
! Either evaluate parameter directly at IP,
6923
! or first at nodes and then using basis functions at IP.
6924
! The latter is the default.
6925
!------------------------------------------------------------------
6926
IF( Handle % EvaluateAtIp ) THEN
6927
IF(.NOT. PRESENT(Basis)) THEN
6928
CALL Fatal('ListGetElementReal','Parameter > Basis < is required for: '//TRIM(Handle % Name))
6929
END IF
6930
6931
! If we get back to the same element than last time use the data already
6932
! retrieved. If the element is new then get the data in every node of the
6933
! current element, or only in the 1st node if it is constant.
6934
6935
IF( ASSOCIATED( PElement, Handle % Element ) ) THEN
6936
IF( PRESENT( Indexes ) ) THEN
6937
ni = SIZE( Indexes )
6938
NodeIndexes => Indexes
6939
ELSE
6940
ni = Handle % Element % TYPE % NumberOfNodes
6941
NodeIndexes => PElement % NodeIndexes
6942
END IF
6943
6944
ParF => Handle % ParValues
6945
ELSE
6946
IF( .NOT. Handle % AllocationsDone ) THEN
6947
ni = CurrentModel % Mesh % MaxElementNodes
6948
ALLOCATE( Handle % Values(ni) )
6949
Handle % Values = 0.0_dp
6950
ALLOCATE( Handle % ParValues(MAX_FNC,ni), Handle % ParUsed(MAX_FNC) )
6951
Handle % ParValues = 0.0_dp
6952
Handle % ParUsed = .FALSE.
6953
Handle % AllocationsDone = .TRUE.
6954
END IF
6955
6956
Handle % Element => PElement
6957
IF( PRESENT( Indexes ) ) THEN
6958
ni = SIZE( Indexes )
6959
NodeIndexes => Indexes
6960
ELSE
6961
ni = PElement % TYPE % NumberOfNodes
6962
NodeIndexes => PElement % NodeIndexes
6963
END IF
6964
6965
! First fetch the nodal fields so that they may be evaluated at IP's
6966
IF( ptr % TYPE == LIST_TYPE_VARIABLE_SCALAR .OR. &
6967
ptr % TYPE == LIST_TYPE_VARIABLE_SCALAR_STR .OR. &
6968
ptr % TYPE == LIST_TYPE_VARIABLE_TENSOR .OR. &
6969
ptr % Type == LIST_TYPE_VARIABLE_TENSOR_STR ) THEN
6970
6971
! These might not have been initialized if this has mixed evaluation strategies
6972
IF(.NOT. ASSOCIATED( Handle % ParValues )) THEN
6973
ALLOCATE( Handle % ParValues(MAX_FNC,CurrentModel % Mesh % MaxElementNodes), &
6974
Handle % ParUsed(MAX_FNC) )
6975
Handle % ParValues = 0.0_dp
6976
Handle % ParUsed = .FALSE.
6977
END IF
6978
6979
CALL VarsToValuesOnNodesWhich( Handle % VarCount, Handle % VarTable, &
6980
Handle % ParUsed, j)
6981
j0 = Handle % IntVarCount+1
6982
6983
DO i=1,ni
6984
k = NodeIndexes(i)
6985
6986
CALL VarsToValuesOnNodes( Handle % VarCount, Handle % VarTable, &
6987
k, T, j, Handle % IntVarCount, tstep )
6988
6989
Handle % ParNo = j
6990
Handle % ParValues(j0:j,i) = T(j0:j)
6991
6992
! If the dependency table includes just global values (such as time)
6993
! the values will be the same for all element entries.
6994
IF( Handle % GlobalInList ) EXIT
6995
END DO
6996
END IF
6997
ParF => Handle % ParValues
6998
END IF
6999
7000
7001
SELECT CASE(ptr % TYPE)
7002
7003
CASE( LIST_TYPE_VARIABLE_SCALAR )
7004
7005
IF( Handle % IntVarCount > 0 ) THEN
7006
T(1:Handle % IntVarCount) = DummyVals
7007
END IF
7008
j0 = Handle % IntVarCount+1
7009
DO j=j0,Handle % VarCount
7010
IF( Handle % ParUsed(j) ) THEN
7011
T(j) = SUM( Basis(1:ni) * Handle % ParValues(j,1:ni) )
7012
END IF
7013
END DO
7014
7015
! This one only deals with the variables on IPs, nodal ones are fetched separately
7016
IF( Handle % SomeVarAtIp ) THEN
7017
CALL VarsToValuesOnIps( Handle % VarCount, Handle % VarTable, T, j, &
7018
GaussPoint, Basis, Handle % IntVarCount, tstep )
7019
END IF
7020
7021
! there is no node index, pass the negative GaussPoint as to separate it from positive node index
7022
IF ( ptr % PROCEDURE /= 0 ) THEN
7023
IF( PRESENT( GaussPoint ) ) THEN
7024
j = -GaussPoint
7025
ELSE
7026
j = 0
7027
END IF
7028
!CALL ListPushActiveName(Handle % name)
7029
7030
Rvalue = ExecRealFunction( ptr % PROCEDURE,CurrentModel, j, T )
7031
!CALL ListPopActiveName()
7032
ELSE
7033
RValue = InterpolateCurve( ptr % TValues,ptr % FValues(1,1,:), &
7034
T(1), ptr % CubicCoeff )
7035
END IF
7036
7037
CASE( LIST_TYPE_VARIABLE_SCALAR_STR )
7038
7039
IF( Handle % IntVarCount > 0 ) THEN
7040
T(1:Handle % IntVarCount) = DummyVals
7041
END IF
7042
j0 = Handle % IntVarCount + 1
7043
DO j=j0,Handle % ParNo
7044
IF( Handle % ParUsed(j) ) THEN
7045
T(j) = SUM( Basis(1:ni) * Handle % ParValues(j,1:ni) )
7046
END IF
7047
END DO
7048
7049
! This one only deals with the variables on IPs, nodal ones have been fecthed already
7050
IF( Handle % SomeVarAtIp ) THEN
7051
CALL VarsToValuesOnIps( Handle % VarCount, Handle % VarTable, T, j, GaussPoint, Basis, &
7052
Handle % IntVarCount, tstep )
7053
END IF
7054
7055
IF ( ptr % LuaFun ) THEN
7056
CALL ElmerEvalLua(LuaState, ptr, T, RValue, Handle % ParNo )
7057
ELSE
7058
Rvalue = GetMatcReal(Ptr % Cvalue,Handle % ParNo,T)
7059
END IF
7060
7061
CASE( LIST_TYPE_CONSTANT_SCALAR_PROC )
7062
7063
IF ( ptr % PROCEDURE /= 0 ) THEN
7064
x = SUM( Basis(1:ni) * CurrentModel % Mesh % Nodes % x( NodeIndexes(1:ni) ) )
7065
y = SUM( Basis(1:ni) * CurrentModel % Mesh % Nodes % y( NodeIndexes(1:ni) ) )
7066
z = SUM( Basis(1:ni) * CurrentModel % Mesh % Nodes % z( NodeIndexes(1:ni) ) )
7067
7068
!CALL ListPushActiveName(Handle % name)
7069
RValue = ExecConstRealFunction( ptr % PROCEDURE,CurrentModel,x,y,z)
7070
!CALL ListPopActiveName()
7071
ELSE
7072
CALL Fatal('ListGetElementReal','Constant scalar evaluation failed at ip!')
7073
END IF
7074
7075
CASE ( LIST_TYPE_CONSTANT_TENSOR )
7076
7077
n = SIZE( Handle % Rtensor, 1 )
7078
m = SIZE( Handle % Rtensor, 2 )
7079
7080
IF ( ptr % PROCEDURE /= 0 ) THEN
7081
CALL Fatal('ListGetElementReal','No proper API exists for constant tensors?!')
7082
ELSE
7083
Handle % Rtensor(:,:) = ptr % FValues(:,:,1)
7084
END IF
7085
7086
IF( ABS( ptr % Coeff - 1.0_dp ) > EPSILON( ptr % Coeff ) ) THEN
7087
Handle % Rtensor = ptr % Coeff * Handle % Rtensor
7088
END IF
7089
7090
7091
CASE( LIST_TYPE_VARIABLE_TENSOR )
7092
7093
IF( Handle % IntVarCount > 0 ) THEN
7094
T(1:Handle % IntVarCount) = DummyVals
7095
END IF
7096
j0 = Handle % IntVarCount + 1
7097
DO j=j0,Handle % ParNo
7098
IF( Handle % ParUsed(j) ) THEN
7099
T(j) = SUM( Basis(1:ni) * Handle % ParValues(j,1:ni) )
7100
END IF
7101
END DO
7102
7103
! This one only deals with the variables on IPs, nodal ones are fetched separately
7104
IF( Handle % SomeVarAtIp ) THEN
7105
CALL VarsToValuesOnIps( Handle % VarCount, Handle % VarTable, T, j, GaussPoint, Basis, &
7106
Handle % IntVarCount, tstep )
7107
END IF
7108
7109
! there is no node index, pass the negative GaussPoint as to separate it from positive node index
7110
IF ( ptr % PROCEDURE /= 0 ) THEN
7111
IF( PRESENT( GaussPoint ) ) THEN
7112
j = -GaussPoint
7113
ELSE
7114
j = 0
7115
END IF
7116
!CALL ListPushActiveName(Handle % name)
7117
CALL ExecRealArrayFunction( ptr % PROCEDURE, CurrentModel, &
7118
j, T, Handle % RTensor )
7119
!CALL ListPopActiveName()
7120
ELSE
7121
IF( Handle % ParNo /= 1 ) THEN
7122
CALL Fatal('ListGetElementReal','Table dependence only for one variable!')
7123
END IF
7124
DO j2=1,n
7125
DO k2=1,m
7126
Handle % Rtensor(j2,k2) = InterpolateCurve(ptr % TValues, ptr % FValues(j2,k2,:), &
7127
T(1), ptr % CubicCoeff )
7128
END DO
7129
END DO
7130
END IF
7131
7132
CASE( LIST_TYPE_VARIABLE_TENSOR_STR )
7133
7134
Handle % GlobalInList = .FALSE.
7135
7136
IF( Handle % IntVarCount > 0 ) THEN
7137
T(1:Handle % IntVarCount) = DummyVals
7138
END IF
7139
j0 = Handle % IntVarCount + 1
7140
DO j=j0,Handle % ParNo
7141
IF( Handle % ParUsed(j) ) THEN
7142
T(j) = SUM( Basis(1:ni) * Handle % ParValues(j,1:ni) )
7143
END IF
7144
END DO
7145
7146
! This one only deals with the variables on IPs, nodal ones are fetched separately
7147
IF( Handle % SomeVarAtIp ) THEN
7148
CALL VarsToValuesOnIps( Handle % VarCount, Handle % VarTable, T, j, GaussPoint, Basis, &
7149
Handle % IntVarCount, tstep )
7150
END IF
7151
7152
IF ( .NOT. ptr % LuaFun ) THEN
7153
Handle % Rtensor = GetMatcRealArray(ptr % Cvalue,n,m,Handle % ParNo,T)
7154
ELSE
7155
CALL ElmerEvalLua(LuaState, ptr, T, Handle % RTensor, j )
7156
END IF
7157
CASE DEFAULT
7158
7159
CALL Fatal('ListGetElementReal','Unknown case for avaluation at ip: '//I2S(ptr % Type))
7160
7161
END SELECT
7162
7163
ELSE ! .NOT. EvaluteAtIp
7164
7165
! If we get back to the same element than last time use the data already
7166
! retrieved. If the element is new then get the data in every node of the
7167
! current element, or only in the 1st node if it is constant.
7168
7169
IF( Handle % IntVarCount > 0 ) THEN
7170
CALL Fatal('ListGetElementReal','It is assumed that dummy variables are given on IP points only!')
7171
END IF
7172
7173
IF( ASSOCIATED( PElement, Handle % Element ) ) THEN
7174
IF( PRESENT( Indexes ) ) THEN
7175
ni = SIZE( Indexes )
7176
NodeIndexes => Indexes
7177
ELSE
7178
ni = Handle % Element % TYPE % NumberOfNodes
7179
NodeIndexes => PElement % NodeIndexes
7180
END IF
7181
F => Handle % Values
7182
ElementSame = .TRUE.
7183
7184
ELSE
7185
IF( .NOT. Handle % AllocationsDone ) THEN
7186
ni = CurrentModel % Mesh % MaxElementNodes
7187
ALLOCATE( Handle % Values(ni) )
7188
Handle % Values = 0.0_dp
7189
IF( Handle % SomewhereEvaluateAtIp .OR. Handle % EvaluateAtIp ) THEN
7190
ALLOCATE( Handle % ParValues(MAX_FNC,ni), Handle % ParUsed(MAX_FNC) )
7191
Handle % ParValues = 0.0_dp
7192
Handle % ParUsed = .FALSE.
7193
END IF
7194
Handle % AllocationsDone = .TRUE.
7195
END IF
7196
7197
Handle % Element => PElement
7198
F => Handle % Values
7199
7200
IF( PRESENT( Indexes ) ) THEN
7201
ni = SIZE( Indexes )
7202
NodeIndexes => Indexes
7203
ELSE
7204
ni = PElement % TYPE % NumberOfNodes
7205
NodeIndexes => PElement % NodeIndexes
7206
END IF
7207
7208
SELECT CASE(ptr % TYPE)
7209
7210
CASE( LIST_TYPE_CONSTANT_SCALAR )
7211
7212
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
7213
CALL Fatal( 'ListGetElementReal', 'Value type for property ['//TRIM(Handle % Name)// &
7214
'] not used consistently.')
7215
END IF
7216
F(1) = ptr % Coeff * ptr % Fvalues(1,1,1)
7217
7218
7219
CASE( LIST_TYPE_VARIABLE_SCALAR )
7220
!CALL ListPushActiveName(Handle % name)
7221
7222
DO i=1,ni
7223
k = NodeIndexes(i)
7224
7225
CALL VarsToValuesOnNodes( Handle % VarCount, Handle % VarTable, &
7226
k, T, j )
7227
7228
IF ( ptr % PROCEDURE /= 0 ) THEN
7229
F(i) = ptr % Coeff * &
7230
ExecRealFunction( ptr % PROCEDURE,CurrentModel, &
7231
NodeIndexes(i), T )
7232
ELSE
7233
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
7234
CALL Fatal('ListGetElementReal','Value type for property ['//TRIM(Handle % Name)// &
7235
'] not used consistently!')
7236
END IF
7237
F(i) = ptr % Coeff * &
7238
InterpolateCurve( ptr % TValues,ptr % FValues(1,1,:), &
7239
T(1), ptr % CubicCoeff )
7240
7241
! If the dependency table includes just global values (such as time)
7242
! the values will be the same for all element entries.
7243
IF( Handle % GlobalInList ) EXIT
7244
7245
END IF
7246
END DO
7247
!CALL ListPopActiveName()
7248
7249
CASE( LIST_TYPE_CONSTANT_SCALAR_STR )
7250
7251
IF ( ptr % LuaFun ) THEN
7252
CALL Fatal('ListGetElementReal','No routine for constant scalars LUA available!')
7253
ELSE
7254
TVar => VariableGet( CurrentModel % Variables, 'Time' )
7255
F(1) = ptr % Coeff * GetMatcReal(ptr % Cvalue,1,Tvar % values,'st')
7256
END IF
7257
7258
7259
CASE( LIST_TYPE_VARIABLE_SCALAR_STR )
7260
7261
DO i=1,ni
7262
k = NodeIndexes(i)
7263
CALL VarsToValuesOnNodes( Handle % VarCount, Handle % VarTable, &
7264
k, T, j )
7265
IF ( .NOT. ptr % LuaFun ) THEN
7266
IF ( .NOT. ANY( T(1:j)==HUGE(1.0_dp) ) ) THEN
7267
F(i) = ptr % Coeff * GetMatcReal(ptr % Cvalue,j,T)
7268
END IF
7269
ELSE
7270
CALL ElmerEvalLua(LuaState, ptr, T, F(i), j )
7271
END IF
7272
7273
IF( Handle % GlobalInList ) EXIT
7274
END DO
7275
7276
CASE( LIST_TYPE_CONSTANT_SCALAR_PROC )
7277
7278
IF ( ptr % PROCEDURE == 0 ) THEN
7279
CALL Fatal('ListGetElementReal','Value type for property ['//TRIM(Handle % Name)// &
7280
'] not used consistently!')
7281
END IF
7282
7283
!CALL ListPushActiveName(Handle % name)
7284
DO i=1,ni
7285
F(i) = ptr % Coeff * &
7286
ExecConstRealFunction( ptr % PROCEDURE,CurrentModel, &
7287
CurrentModel % Mesh % Nodes % x( NodeIndexes(i) ), &
7288
CurrentModel % Mesh % Nodes % y( NodeIndexes(i) ), &
7289
CurrentModel % Mesh % Nodes % z( NodeIndexes(i) ) )
7290
END DO
7291
!CALL ListPopActiveName()
7292
7293
7294
CASE ( LIST_TYPE_CONSTANT_TENSOR )
7295
7296
n = SIZE( Handle % Rtensor, 1 )
7297
m = SIZE( Handle % Rtensor, 2 )
7298
7299
IF ( ptr % PROCEDURE /= 0 ) THEN
7300
!CALL ListPushActiveName(Handle % name)
7301
DO i=1,n
7302
DO j=1,m
7303
Handle % Rtensor(i,j) = ExecConstRealFunction( ptr % PROCEDURE, &
7304
CurrentModel, 0.0_dp, 0.0_dp, 0.0_dp )
7305
END DO
7306
END DO
7307
!CALL ListPopActiveName()
7308
ELSE
7309
Handle % Rtensor(:,:) = ptr % FValues(:,:,1)
7310
END IF
7311
7312
IF( ABS( ptr % Coeff - 1.0_dp ) > EPSILON( ptr % Coeff ) ) THEN
7313
Handle % Rtensor = ptr % Coeff * Handle % Rtensor
7314
END IF
7315
7316
7317
CASE( LIST_TYPE_VARIABLE_TENSOR )
7318
7319
Handle % GlobalInList = .FALSE.
7320
7321
!CALL ListPushActiveName(Handle % name)
7322
7323
IF( PRESENT( Indexes ) ) THEN
7324
n = SIZE( Indexes )
7325
NodeIndexes => Indexes
7326
ELSE
7327
n = Handle % Element % TYPE % NumberOfNodes
7328
NodeIndexes => Handle % Element % NodeIndexes
7329
END IF
7330
7331
n = SIZE( Handle % Rtensor, 1 )
7332
m = SIZE( Handle % Rtensor, 2 )
7333
7334
DO i=1,ni
7335
k = NodeIndexes(i)
7336
7337
CALL VarsToValuesOnNodes( Handle % VarCount, Handle % VarTable, &
7338
k, T, j )
7339
7340
IF ( ptr % PROCEDURE /= 0 ) THEN
7341
CALL ExecRealArrayFunction( ptr % PROCEDURE, CurrentModel, &
7342
NodeIndexes(i), T, Handle % RTensor )
7343
ELSE
7344
DO j2=1,n
7345
DO k2=1,m
7346
Handle % Rtensor(j2,k2) = InterpolateCurve(ptr % TValues, ptr % FValues(j2,k2,:), &
7347
T(1), ptr % CubicCoeff )
7348
END DO
7349
END DO
7350
END IF
7351
7352
!CALL ListPopActiveName()
7353
7354
IF( ABS( ptr % Coeff - 1.0_dp ) > EPSILON( ptr % Coeff ) ) THEN
7355
Handle % Rtensor = ptr % Coeff * Handle % Rtensor
7356
END IF
7357
7358
! If all variables are global the Rtensor will be constant
7359
IF( Handle % GlobalInList ) EXIT
7360
7361
Handle % RtensorValues(1:n,1:m,i) = Handle % Rtensor(1:n,1:m)
7362
END DO
7363
7364
CASE( LIST_TYPE_VARIABLE_TENSOR_STR )
7365
7366
Handle % GlobalInList = .FALSE.
7367
7368
!CALL ListPushActiveName(Handle % name)
7369
7370
IF( PRESENT( Indexes ) ) THEN
7371
n = SIZE( Indexes )
7372
NodeIndexes => Indexes
7373
ELSE
7374
n = Handle % Element % TYPE % NumberOfNodes
7375
NodeIndexes => Handle % Element % NodeIndexes
7376
END IF
7377
7378
n = SIZE( Handle % Rtensor, 1 )
7379
m = SIZE( Handle % Rtensor, 2 )
7380
7381
DO i=1,ni
7382
k = NodeIndexes(i)
7383
7384
CALL VarsToValuesOnNodes( Handle % VarCount, Handle % VarTable, &
7385
k, T, j )
7386
7387
IF ( .NOT. ptr % LuaFun ) THEN
7388
7389
Handle % Rtensor = GetMatcRealArray(ptr % Cvalue,n,m,j,T)
7390
7391
ELSE
7392
CALL ElmerEvalLua(LuaState, ptr, T, Handle % RTensor, j )
7393
END IF
7394
!CALL ListPopActiveName()
7395
7396
IF( ABS( ptr % Coeff - 1.0_dp ) > EPSILON( ptr % Coeff ) ) THEN
7397
Handle % Rtensor = ptr % Coeff * Handle % Rtensor
7398
END IF
7399
7400
IF( Handle % GlobalInList ) EXIT
7401
7402
Handle % RtensorValues(1:n,1:m,i) = Handle % Rtensor(1:n,1:m)
7403
END DO
7404
END SELECT
7405
7406
END IF
7407
7408
7409
IF( Handle % Rdim == 0 ) THEN
7410
IF( Handle % GlobalInList ) THEN
7411
RValue = F(1)
7412
ELSE
7413
IF(.NOT. PRESENT(Basis)) THEN
7414
CALL Fatal('ListGetElementReal','Parameter > Basis < is required for: '//TRIM(Handle % Name))
7415
ELSE
7416
RValue = SUM( Basis(1:ni) * F(1:ni) )
7417
END IF
7418
END IF
7419
ELSE
7420
Rtensor => Handle % Rtensor
7421
Rdim = Handle % Rdim
7422
7423
IF( .NOT. Handle % GlobalInList ) THEN
7424
IF(.NOT. PRESENT(Basis)) THEN
7425
CALL Fatal('ListGetElementReal','Parameter > Basis < is required for: '//TRIM(Handle % Name))
7426
ELSE
7427
DO j2=1,SIZE( Handle % RTensor, 1 )
7428
DO k2=1,SIZE( Handle % RTensor, 2 )
7429
Handle % RTensor(j2,k2) = SUM( Basis(1:ni) * Handle % RtensorValues(j2,k2,1:ni) )
7430
END DO
7431
END DO
7432
END IF
7433
END IF
7434
END IF
7435
7436
END IF
7437
7438
IF ( Handle % GotMinv ) THEN
7439
IF ( RValue < Handle % minv ) THEN
7440
WRITE( Message,*) 'Given value ',RValue, ' for property: ', '[', TRIM(Handle % Name),']', &
7441
' smaller than given minimum: ', Handle % minv
7442
CALL Fatal( 'ListGetElementReal', Message )
7443
END IF
7444
END IF
7445
7446
IF ( Handle % GotMaxv ) THEN
7447
IF ( RValue > Handle % maxv ) THEN
7448
WRITE( Message,*) 'Given value ',RValue, ' for property: ', '[', TRIM(Handle % Name),']', &
7449
' larger than given maximum ', Handle % maxv
7450
CALL Fatal( 'ListGetElementReal', Message )
7451
END IF
7452
END IF
7453
7454
END FUNCTION ListGetElementReal
7455
!------------------------------------------------------------------------------
7456
7457
7458
!------------------------------------------------------------------------------
7459
!> This is just a wrapper for getting the imaginary part of the keyword if it
7460
!> has been properly initialized. For the solver modules it is more convenient
7461
!> as the code becomes more compact when using the "HandleIm" field instead of a
7462
!> totally new handle.
7463
!------------------------------------------------------------------------------
7464
FUNCTION ListGetElementIm( Handle,Basis,Element,Found,Indexes,&
7465
GaussPoint,Rdim,Rtensor) RESULT(Rvalue)
7466
!------------------------------------------------------------------------------
7467
TYPE(ValueHandle_t) :: Handle
7468
REAL(KIND=dp), OPTIONAL :: Basis(:)
7469
LOGICAL, OPTIONAL :: Found
7470
TYPE(Element_t), POINTER, OPTIONAL :: Element
7471
INTEGER, POINTER, OPTIONAL :: Indexes(:)
7472
INTEGER, OPTIONAL :: GaussPoint
7473
INTEGER, OPTIONAL :: Rdim
7474
REAL(KIND=dp), POINTER, OPTIONAL :: Rtensor(:,:)
7475
REAL(KIND=dp) :: Rvalue
7476
7477
IF(.NOT. ASSOCIATED( Handle % HandleIm ) ) THEN
7478
CALL Fatal('ListGetElementIm','Initialize with imaginary component!')
7479
END IF
7480
Rvalue = ListGetElementReal(Handle % HandleIm,Basis,Element,Found,Indexes,&
7481
GaussPoint,Rdim,Rtensor)
7482
END FUNCTION ListGetElementIm
7483
7484
7485
!------------------------------------------------------------------------------
7486
!> This is just a wrapper for getting both the real and imaginary part of the keyword if it
7487
!> has been properly initialized. For the solver modules it is convenient since the
7488
!> final code is more compact. This does not work with vector valued keywords yet!
7489
!------------------------------------------------------------------------------
7490
FUNCTION ListGetElementComplex( Handle,Basis,Element,Found,Indexes,&
7491
GaussPoint,Rdim,Rtensor) RESULT(Zvalue)
7492
!------------------------------------------------------------------------------
7493
TYPE(ValueHandle_t) :: Handle
7494
REAL(KIND=dp), OPTIONAL :: Basis(:)
7495
LOGICAL, OPTIONAL :: Found
7496
TYPE(Element_t), POINTER, OPTIONAL :: Element
7497
INTEGER, POINTER, OPTIONAL :: Indexes(:)
7498
INTEGER, OPTIONAL :: GaussPoint
7499
INTEGER, OPTIONAL :: Rdim
7500
REAL(KIND=dp), POINTER, OPTIONAL :: Rtensor(:,:)
7501
COMPLEX(KIND=dp) :: Zvalue
7502
7503
REAL(KIND=dp) :: RValue, Ivalue
7504
LOGICAL :: RFound
7505
7506
IF(.NOT. ASSOCIATED( Handle % HandleIm ) ) THEN
7507
CALL Fatal('ListGetElementComplex','Initialize with imaginary component!')
7508
END IF
7509
7510
IF( Handle % NotPresentAnywhere .AND. Handle % HandleIm % NotPresentAnywhere ) THEN
7511
IF(PRESENT(Found)) Found = .FALSE.
7512
Zvalue = CMPLX( Handle % DefRValue, 0.0_dp, KIND=dp )
7513
RETURN
7514
END IF
7515
7516
Rvalue = ListGetElementReal(Handle,Basis,Element,Found,Indexes,GaussPoint)
7517
IF( PRESENT( Found ) ) RFound = Found
7518
7519
Ivalue = ListGetElementReal(Handle % HandleIm,Basis,Element,Found,Indexes,GaussPoint)
7520
IF( PRESENT( Found ) ) Found = Found .OR. RFound
7521
7522
Zvalue = CMPLX( Rvalue, Ivalue, KIND=dp )
7523
7524
END FUNCTION ListGetElementComplex
7525
7526
7527
!------------------------------------------------------------------------------
7528
!> This is just a wrapper for getting a 3D real vector.
7529
!------------------------------------------------------------------------------
7530
FUNCTION ListGetElementReal3D( Handle,Basis,Element,Found,Indexes,&
7531
GaussPoint,Rdim,Rtensor) RESULT(RValue3D)
7532
!------------------------------------------------------------------------------
7533
TYPE(ValueHandle_t) :: Handle
7534
REAL(KIND=dp), OPTIONAL :: Basis(:)
7535
LOGICAL, OPTIONAL :: Found
7536
TYPE(Element_t), POINTER, OPTIONAL :: Element
7537
INTEGER, POINTER, OPTIONAL :: Indexes(:)
7538
INTEGER, OPTIONAL :: GaussPoint
7539
INTEGER, OPTIONAL :: Rdim
7540
REAL(KIND=dp), POINTER, OPTIONAL :: Rtensor(:,:)
7541
REAL(KIND=dp) :: RValue3D(3)
7542
7543
LOGICAL :: Found1, Found2
7544
7545
IF(.NOT. ASSOCIATED( Handle % Handle2 ) ) THEN
7546
CALL Fatal('ListGetElementReal3D','Initialize with 3D components!')
7547
END IF
7548
7549
IF( Handle % NotPresentAnywhere .AND. Handle % Handle2 % NotPresentAnywhere &
7550
.AND. Handle % Handle3 % NotPresentAnywhere ) THEN
7551
IF(PRESENT(Found)) Found = .FALSE.
7552
RValue3D = 0.0_dp
7553
RETURN
7554
END IF
7555
7556
Rvalue3D(1) = ListGetElementReal(Handle,Basis,Element,Found,Indexes,GaussPoint)
7557
IF( PRESENT( Found ) ) Found1 = Found
7558
7559
Rvalue3D(2) = ListGetElementReal(Handle % Handle2,Basis,Element,Found,Indexes,GaussPoint)
7560
IF( PRESENT( Found ) ) Found2 = Found
7561
7562
Rvalue3D(3) = ListGetElementReal(Handle % Handle3,Basis,Element,Found,Indexes,GaussPoint)
7563
IF( PRESENT( Found ) ) Found = Found1 .OR. Found2 .OR. Found
7564
7565
END FUNCTION ListGetElementReal3D
7566
7567
7568
!------------------------------------------------------------------------------
7569
!> This is a wrapper to get gradient of a real valued keyword with functional dependencies.
7570
!------------------------------------------------------------------------------
7571
FUNCTION ListGetElementRealGrad( Handle,dBasisdx,Element,Found,Indexes,tstep) RESULT(RGrad)
7572
!------------------------------------------------------------------------------
7573
TYPE(ValueHandle_t) :: Handle
7574
! dBasisdx is required since it is used to evaluate the gradient
7575
REAL(KIND=dp) :: dBasisdx(:,:)
7576
LOGICAL, OPTIONAL :: Found
7577
TYPE(Element_t), POINTER, OPTIONAL :: Element
7578
INTEGER, POINTER, OPTIONAL :: Indexes(:)
7579
INTEGER, OPTIONAL :: tstep
7580
REAL(KIND=dp) :: RGrad(3)
7581
LOGICAL :: Lfound
7582
INTEGER :: i
7583
7584
RGrad = 0.0_dp
7585
7586
IF( Handle % NotPresentAnywhere ) THEN
7587
IF( PRESENT( Found ) ) Found = .FALSE.
7588
RETURN
7589
END IF
7590
7591
! Derivative of constant is zero
7592
IF( Handle % ConstantEverywhere ) THEN
7593
IF( PRESENT( Found ) ) Found = .TRUE.
7594
RETURN
7595
END IF
7596
7597
! Obtain gradient of a scalar field going through the partial derivatives of the components
7598
DO i=1,3
7599
RGrad(i) = ListGetElementReal(Handle,dBasisdx(:,i),Element,Lfound,Indexes,tstep=tstep)
7600
! If we don't have it needless to contunue to 2nd and 3rd dimensions
7601
IF(.NOT. Lfound ) EXIT
7602
END DO
7603
IF( PRESENT( Found ) ) Found = Lfound
7604
7605
END FUNCTION ListGetElementRealGrad
7606
7607
7608
!------------------------------------------------------------------------------
7609
!> This is just a wrapper for getting divergence of a 3D real vector neatly.
7610
!------------------------------------------------------------------------------
7611
FUNCTION ListGetElementRealDiv( Handle,dBasisdx,Element,Found,Indexes) RESULT(Rdiv)
7612
!------------------------------------------------------------------------------
7613
TYPE(ValueHandle_t) :: Handle
7614
! dBasisdx is required since it is used to evaluate the divergence
7615
REAL(KIND=dp) :: dBasisdx(:,:)
7616
LOGICAL, OPTIONAL :: Found
7617
TYPE(Element_t), POINTER, OPTIONAL :: Element
7618
INTEGER, POINTER, OPTIONAL :: Indexes(:)
7619
REAL(KIND=dp) :: Rdiv, Rdiv_comps(3)
7620
7621
LOGICAL :: Found1
7622
7623
IF(PRESENT(Found)) Found = .FALSE.
7624
Rdiv = 0.0_dp
7625
7626
IF(.NOT. ASSOCIATED( Handle % Handle2 ) ) THEN
7627
CALL Fatal('ListGetElementReal3D','Initialize with 3D components!')
7628
END IF
7629
7630
IF( Handle % NotPresentAnywhere .AND. Handle % Handle2 % NotPresentAnywhere &
7631
.AND. Handle % Handle3 % NotPresentAnywhere ) THEN
7632
RETURN
7633
END IF
7634
7635
Rdiv_comps(1) = ListGetElementReal(Handle,dBasisdx(:,1),Element,Found1,Indexes)
7636
! We can only take Div of a vector field if all components are present
7637
IF(.NOT. Found1) RETURN
7638
Rdiv_comps(2) = ListGetElementReal(Handle % Handle2,dBasisdx(:,2),Element,Found1,Indexes)
7639
Rdiv_comps(3) = ListGetElementReal(Handle % Handle3,dBasisdx(:,3),Element,Found1,Indexes)
7640
7641
Rdiv = SUM(Rdiv_comps)
7642
IF( PRESENT( Found ) ) Found = .TRUE.
7643
7644
END FUNCTION ListGetElementRealDiv
7645
7646
7647
7648
!------------------------------------------------------------------------------
7649
!> This is just a wrapper for getting a 3D complex vector.
7650
!------------------------------------------------------------------------------
7651
FUNCTION ListGetElementComplex3D( Handle,Basis,Element,Found,Indexes,&
7652
GaussPoint,Rdim,Rtensor) RESULT(ZValue3D)
7653
!------------------------------------------------------------------------------
7654
TYPE(ValueHandle_t) :: Handle
7655
REAL(KIND=dp), OPTIONAL :: Basis(:)
7656
LOGICAL, OPTIONAL :: Found
7657
TYPE(Element_t), POINTER, OPTIONAL :: Element
7658
INTEGER, POINTER, OPTIONAL :: Indexes(:)
7659
INTEGER, OPTIONAL :: GaussPoint
7660
INTEGER, OPTIONAL :: Rdim
7661
REAL(KIND=dp), POINTER, OPTIONAL :: Rtensor(:,:)
7662
COMPLEX(KIND=dp) :: ZValue3D(3)
7663
7664
REAL(KIND=dp) :: RValue3D(3), IValue3D(3)
7665
LOGICAL :: RFound
7666
7667
IF(.NOT. ASSOCIATED( Handle % HandleIm ) ) THEN
7668
CALL Fatal('ListGetElementComplex3D','Initialize with imaginary component!')
7669
END IF
7670
7671
Rvalue3D = ListGetElementReal3D(Handle,Basis,Element,Found,Indexes,GaussPoint)
7672
IF( PRESENT( Found ) ) RFound = Found
7673
7674
Ivalue3D = ListGetElementReal3D(Handle % HandleIm,Basis,Element,Found,Indexes,GaussPoint)
7675
IF( PRESENT( Found ) ) Found = Found .OR. RFound
7676
7677
Zvalue3D = CMPLX( Rvalue3D, Ivalue3D, KIND=dp )
7678
7679
END FUNCTION ListGetElementComplex3D
7680
7681
7682
!------------------------------------------------------------------------------
7683
!> Gets a real valued parameter in all the Gaussian integration points.
7684
!------------------------------------------------------------------------------
7685
FUNCTION ListGetElementRealVec( Handle,ngp,BasisVec,Element,Found ) RESULT( Rvalues )
7686
!------------------------------------------------------------------------------
7687
TYPE(ValueHandle_t) :: Handle
7688
INTEGER :: ngp
7689
REAL(KIND=dp), OPTIONAL :: BasisVec(:,:)
7690
LOGICAL, OPTIONAL :: Found
7691
TYPE(Element_t), POINTER, OPTIONAL :: Element
7692
REAL(KIND=dp), POINTER :: Rvalues(:)
7693
!------------------------------------------------------------------------------
7694
TYPE(Variable_t), POINTER :: Variable, CVar, TVar
7695
TYPE(ValueListEntry_t), POINTER :: ptr
7696
INTEGER, POINTER :: NodeIndexes(:)
7697
REAL(KIND=dp) :: T(MAX_FNC),x,y,z, RValue
7698
REAL(KIND=dp), POINTER :: F(:)
7699
REAL(KIND=dp), POINTER :: ParF(:,:)
7700
INTEGER :: i,j,k,k1,l,l0,l1,lsize,n,bodyid,id,node,gp
7701
TYPE(Element_t), POINTER :: PElement
7702
TYPE(ValueList_t), POINTER :: List
7703
LOGICAL :: AllGlobal, SomeAtIp, SomeAtNodes, ListSame, ListFound, &
7704
GotIt, IntFound, SizeSame
7705
!------------------------------------------------------------------------------
7706
7707
IF( Handle % nValuesVec < ngp ) THEN
7708
IF( Handle % nValuesVec > 0 ) THEN
7709
DEALLOCATE( Handle % ValuesVec )
7710
END IF
7711
ALLOCATE( Handle % ValuesVec(ngp) )
7712
Handle % nValuesVec = ngp
7713
7714
IF( Handle % ConstantEverywhere ) THEN
7715
Handle % ValuesVec = Handle % Rvalue
7716
ELSE
7717
Handle % ValuesVec = Handle % DefRValue
7718
END IF
7719
! If size is increased we need to ensure that even constants will be rechecked.
7720
Handle % ListId = -1
7721
SizeSame = .FALSE.
7722
ELSE
7723
SizeSame = .TRUE.
7724
END IF
7725
7726
! The results are always returned from the Handle % Values
7727
Rvalues => Handle % ValuesVec
7728
7729
! If value is not present anywhere then return False
7730
IF( Handle % NotPresentAnywhere ) THEN
7731
IF(PRESENT(Found)) Found = .FALSE.
7732
RETURN
7733
END IF
7734
7735
! If the value is known to be globally constant return it asap.
7736
IF( Handle % ConstantEverywhere ) THEN
7737
IF(PRESENT(Found)) Found = .TRUE.
7738
RETURN
7739
END IF
7740
7741
! Find the pointer to the element, if not given
7742
IF( PRESENT( Element ) ) THEN
7743
PElement => Element
7744
ELSE
7745
PElement => CurrentModel % CurrentElement
7746
END IF
7747
7748
! We know by initialization the list entry type that the keyword has
7749
! Find the correct list to look the keyword in.
7750
! Bulk and boundary elements are treated separately.
7751
List => ElementHandleList( PElement, Handle, ListSame, ListFound )
7752
7753
! If the provided list is the same as last time, also the keyword will
7754
! be sitting at the same place, otherwise find it in the new list
7755
IF( ListSame .AND. SizeSame ) THEN
7756
IF( PRESENT( Found ) ) Found = Handle % Found
7757
IF( .NOT. Handle % Found ) RETURN
7758
IF( Handle % GlobalInList ) THEN
7759
RETURN
7760
ELSE
7761
ptr => Handle % ptr % head
7762
END IF
7763
ELSE IF( ListFound ) THEN
7764
7765
ptr => ListFind(List,Handle % Name,IntFound)
7766
IF(PRESENT(Found)) Found = IntFound
7767
Handle % Found = IntFound
7768
7769
IF(.NOT. IntFound ) THEN
7770
IF( Handle % UnfoundFatal ) THEN
7771
CALL Fatal('ListGetElementRealVec','Could not find required keyword in list: '//TRIM(Handle % Name))
7772
END IF
7773
Handle % ValuesVec = Handle % DefRValue
7774
RETURN
7775
END IF
7776
7777
Handle % Ptr % Head => ptr
7778
7779
! It does not make sense to evaluate global variables at IP
7780
IF( Handle % SomewhereEvaluateAtIp ) THEN
7781
! Check whether the keyword should be evaluated at integration point directly
7782
! Only these dependency type may depend on position
7783
IF( ptr % TYPE == LIST_TYPE_VARIABLE_SCALAR .OR. &
7784
ptr % TYPE == LIST_TYPE_VARIABLE_SCALAR_STR .OR. &
7785
ptr % TYPE == LIST_TYPE_CONSTANT_SCALAR_PROC ) THEN
7786
! Check whether the keyword should be evaluated at integration point directly
7787
Handle % EvaluateAtIp = ListGetLogical( List, TRIM( Handle % Name )//' At IP',GotIt )
7788
ELSE
7789
Handle % EvaluateAtIp = .FALSE.
7790
END IF
7791
END IF
7792
7793
7794
IF( ptr % DepNameLen > 0 ) THEN
7795
CALL ListParseStrToVars( Ptr % DependName, Ptr % DepNameLen, &
7796
Handle % Name, Handle % VarCount, Handle % VarTable, &
7797
SomeAtIp, SomeAtNodes, AllGlobal, 0, List )
7798
IF( SomeAtIp ) Handle % EvaluateAtIp = .TRUE.
7799
Handle % GlobalInList = ( AllGlobal .AND. ptr % PROCEDURE == 0 )
7800
IF( AllGlobal ) Handle % EvaluateAtIp = .FALSE.
7801
Handle % SomeVarAtIp = SomeAtIp
7802
ELSE
7803
Handle % GlobalInList = ( ptr % PROCEDURE == 0 )
7804
END IF
7805
7806
IF( Handle % IntVarCount > 0 ) THEN
7807
CALL Fatal('ListGetElementRealVec','Not yet implemented for dummy variables!')
7808
END IF
7809
7810
ELSE
7811
IF( Handle % UnfoundFatal ) THEN
7812
CALL Fatal('ListGetElementRealVec','Could not find list for required keyword: '//TRIM(Handle % Name))
7813
END IF
7814
IF( .NOT. Handle % AllocationsDone ) THEN
7815
n = CurrentModel % Mesh % MaxElementNodes
7816
ALLOCATE( Handle % Values(n) )
7817
Handle % Values = 0.0_dp
7818
IF( Handle % SomewhereEvaluateAtIp .OR. Handle % EvaluateAtIp ) THEN
7819
ALLOCATE( Handle % ParValues(MAX_FNC,n), Handle % ParUsed(MAX_FNC) )
7820
Handle % ParValues = 0.0_dp
7821
Handle % ParUsed = .FALSE.
7822
END IF
7823
Handle % AllocationsDone = .TRUE.
7824
END IF
7825
Handle % ValuesVec = Handle % DefRValue
7826
IF( PRESENT(Found) ) THEN
7827
Found = .FALSE.
7828
Handle % Found = .FALSE.
7829
END IF
7830
RETURN
7831
END IF
7832
7833
! Either evaluate parameter directly at IP,
7834
! or first at nodes and then using basis functions at IP.
7835
! The later is the default.
7836
!------------------------------------------------------------------
7837
IF( Handle % EvaluateAtIp ) THEN
7838
7839
IF(.NOT. PRESENT(BasisVec)) THEN
7840
CALL Fatal('ListGetElementRealVec','Parameter > Basis < is required for: '//TRIM(Handle % Name))
7841
END IF
7842
7843
IF( .NOT. Handle % AllocationsDone ) THEN
7844
n = CurrentModel % Mesh % MaxElementNodes
7845
ALLOCATE( Handle % Values(n) )
7846
Handle % Values = 0.0_dp
7847
ALLOCATE( Handle % ParValues(MAX_FNC,n) )
7848
Handle % ParValues = 0.0_dp
7849
Handle % AllocationsDone = .TRUE.
7850
END IF
7851
7852
Handle % Element => PElement
7853
n = PElement % TYPE % NumberOfNodes
7854
NodeIndexes => PElement % NodeIndexes
7855
7856
7857
IF( ptr % TYPE == LIST_TYPE_VARIABLE_SCALAR .OR. &
7858
ptr % TYPE == LIST_TYPE_VARIABLE_SCALAR_STR .OR. &
7859
ptr % TYPE == LIST_TYPE_VARIABLE_TENSOR .OR. &
7860
ptr % TYPE == LIST_TYPE_VARIABLE_TENSOR_STR ) THEN
7861
7862
! These might not have been initialized if this is has mixed evaluation strategies
7863
IF(.NOT. ASSOCIATED( Handle % ParValues )) THEN
7864
ALLOCATE( Handle % ParValues(MAX_FNC,CurrentModel % Mesh % MaxElementNodes) )
7865
Handle % ParValues = 0.0_dp
7866
END IF
7867
7868
DO i=1,n
7869
node = NodeIndexes(i)
7870
CALL VarsToValuesOnNodes( Handle % VarCount, Handle % VarTable, node, T, j )
7871
7872
IF( Handle % GlobalInList ) THEN
7873
CALL Warn('ListGetElementRealVec','Constant expression need not be evaluated at IPs!')
7874
END IF
7875
7876
Handle % ParNo = j
7877
Handle % ParValues(1:j,i) = T(1:j)
7878
END DO
7879
7880
ParF => Handle % ParValues
7881
END IF
7882
7883
7884
SELECT CASE(ptr % TYPE)
7885
7886
CASE( LIST_TYPE_VARIABLE_SCALAR )
7887
7888
! there is no node index, so use zero
7889
IF ( ptr % PROCEDURE /= 0 ) THEN
7890
!CALL ListPushActiveName(Handle % name)
7891
node = 0
7892
7893
DO gp = 1, ngp
7894
DO j=1,Handle % ParNo
7895
T(j) = SUM( BasisVec(gp,1:n) * ParF(j,1:n) )
7896
END DO
7897
Rvalue = ExecRealFunction( ptr % PROCEDURE, CurrentModel, node, T )
7898
Handle % ValuesVec(gp) = RValue
7899
END DO
7900
!CALL ListPopActiveName()
7901
ELSE
7902
DO gp = 1, ngp
7903
DO j=1,Handle % ParNo
7904
T(j) = SUM( BasisVec(gp,1:n) * ParF(j,1:n) )
7905
END DO
7906
RValue = InterpolateCurve( ptr % TValues,ptr % FValues(1,1,:), &
7907
T(1), ptr % CubicCoeff )
7908
Handle % ValuesVec(gp) = RValue
7909
END DO
7910
END IF
7911
7912
CASE( LIST_TYPE_VARIABLE_SCALAR_STR )
7913
7914
! there is no node index, so use zero
7915
node = 0
7916
7917
DO gp = 1, ngp
7918
DO j=1,Handle % ParNo
7919
T(j) = SUM( BasisVec(gp,1:n) * Handle % ParValues(j,1:n) )
7920
END DO
7921
7922
! This one only deals with the variables on IPs, nodal ones have been fecthed already
7923
IF( Handle % SomeVarAtIp ) THEN
7924
CALL VarsToValuesOnIps( Handle % VarCount, Handle % VarTable, T, j, gp, BasisVec(gp,1:n) )
7925
END IF
7926
7927
IF ( .NOT. ptr % LuaFun ) THEN
7928
Rvalue = GetMatcReal(ptr % Cvalue,Handle % Parno,T)
7929
ELSE
7930
CALL ElmerEvalLua(LuaState, ptr, T, RValue, j)
7931
END IF
7932
Handle % ValuesVec(gp) = RValue
7933
END DO
7934
7935
7936
CASE( LIST_TYPE_CONSTANT_SCALAR_PROC )
7937
7938
IF ( ptr % PROCEDURE /= 0 ) THEN
7939
!CALL ListPushActiveName(Handle % name)
7940
7941
DO gp = 1, ngp
7942
7943
x = SUM(BasisVec(gp,1:n) * CurrentModel % Mesh % Nodes % x( NodeIndexes(1:n)))
7944
y = SUM(BasisVec(gp,1:n) * CurrentModel % Mesh % Nodes % y( NodeIndexes(1:n)))
7945
z = SUM(BasisVec(gp,1:n) * CurrentModel % Mesh % Nodes % z( NodeIndexes(1:n)))
7946
7947
RValue = ExecConstRealFunction( ptr % PROCEDURE,CurrentModel,x,y,z)
7948
Handle % ValuesVec(gp) = RValue
7949
END DO
7950
!CALL ListPopActiveName()
7951
7952
ELSE
7953
CALL Fatal('ListGetElementRealVec','Constant scalar evaluation failed at ip!')
7954
END IF
7955
7956
CASE DEFAULT
7957
7958
CALL Fatal('ListGetElementRealVec','Unknown case for avaluation at ip')
7959
7960
END SELECT
7961
7962
ELSE
7963
7964
IF( .NOT. Handle % AllocationsDone ) THEN
7965
n = CurrentModel % Mesh % MaxElementNodes
7966
ALLOCATE( Handle % Values(n) )
7967
Handle % Values = 0.0_dp
7968
IF( Handle % SomewhereEvaluateAtIp .OR. Handle % EvaluateAtIp ) THEN
7969
ALLOCATE( Handle % ParValues(MAX_FNC,n) )
7970
Handle % ParValues = 0.0_dp
7971
END IF
7972
Handle % AllocationsDone = .TRUE.
7973
END IF
7974
7975
Handle % Element => PElement
7976
n = PElement % TYPE % NumberOfNodes
7977
NodeIndexes => PElement % NodeIndexes
7978
F => Handle % Values
7979
7980
SELECT CASE(ptr % TYPE)
7981
7982
CASE( LIST_TYPE_CONSTANT_SCALAR )
7983
7984
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
7985
CALL Fatal( 'ListGetElementRealVec', 'Value type for property ['//TRIM(Handle % Name)// &
7986
'] not used consistently.')
7987
END IF
7988
F(1) = ptr % Coeff * ptr % Fvalues(1,1,1)
7989
RValues = F(1)
7990
7991
7992
CASE( LIST_TYPE_VARIABLE_SCALAR )
7993
7994
!CALL ListPushActiveName(Handle % name)
7995
7996
DO i=1,n
7997
node = NodeIndexes(i)
7998
CALL VarsToValuesOnNodes( Handle % VarCount, Handle % VarTable, node, T, j )
7999
8000
IF ( ptr % PROCEDURE /= 0 ) THEN
8001
F(i) = ptr % Coeff * &
8002
ExecRealFunction( ptr % PROCEDURE,CurrentModel, &
8003
NodeIndexes(i), T )
8004
ELSE
8005
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
8006
CALL Fatal( 'ListGetElementRealVec', 'Value type for property ['//TRIM(Handle % Name)// &
8007
'] not used consistently.')
8008
END IF
8009
F(i) = ptr % Coeff * &
8010
InterpolateCurve( ptr % TValues,ptr % FValues(1,1,:), &
8011
T(1), ptr % CubicCoeff )
8012
8013
! If the dependency table includes just global values (such as time)
8014
! the values will be the same for all element entries.
8015
IF( Handle % GlobalInList ) EXIT
8016
END IF
8017
END DO
8018
8019
IF( Handle % GlobalInList ) THEN
8020
Handle % ValuesVec = F(1)
8021
ELSE
8022
Handle % ValuesVec(1:ngp) = MATMUL( BasisVec(1:ngp,1:n), F(1:n) )
8023
END IF
8024
!CALL ListPopActiveName()
8025
8026
8027
CASE( LIST_TYPE_CONSTANT_SCALAR_STR )
8028
8029
TVar => VariableGet( CurrentModel % Variables, 'Time' )
8030
Handle % ValuesVec = ptr % Coeff * GetMatcReal(ptr % Cvalue,1,Tvar % Values,'st')
8031
8032
CASE( LIST_TYPE_VARIABLE_SCALAR_STR )
8033
8034
DO i=1,n
8035
k = NodeIndexes(i)
8036
8037
CALL VarsToValuesOnNodes( Handle % VarCount, Handle % VarTable, k, T, j )
8038
8039
IF ( .NOT. ptr % LuaFun ) THEN
8040
IF ( .NOT. ANY( T(1:j)==HUGE(1.0_dp) ) ) THEN
8041
F(i) = ptr % Coeff * GetMatcReal(ptr % Cvalue,j,T)
8042
END IF
8043
ELSE
8044
call ElmerEvalLuaS(LuaState, ptr, T, F(i), j)
8045
F(i) = ptr % coeff * F(i)
8046
END IF
8047
IF( Handle % GlobalInList ) EXIT
8048
END DO
8049
8050
IF( Handle % GlobalInList ) THEN
8051
Handle % ValuesVec = F(1)
8052
ELSE
8053
Handle % ValuesVec(1:ngp) = MATMUL( BasisVec(1:ngp,1:n), F(1:n) )
8054
END IF
8055
8056
CASE( LIST_TYPE_CONSTANT_SCALAR_PROC )
8057
IF ( ptr % PROCEDURE == 0 ) THEN
8058
CALL Fatal( 'ListGetElementRealVec', 'Value type for property ['//TRIM(Handle % Name)// &
8059
'] not used consistently.')
8060
END IF
8061
8062
!CALL ListPushActiveName(Handle % name)
8063
DO i=1,n
8064
F(i) = ptr % Coeff * &
8065
ExecConstRealFunction( ptr % PROCEDURE,CurrentModel, &
8066
CurrentModel % Mesh % Nodes % x( NodeIndexes(i) ), &
8067
CurrentModel % Mesh % Nodes % y( NodeIndexes(i) ), &
8068
CurrentModel % Mesh % Nodes % z( NodeIndexes(i) ) )
8069
END DO
8070
!CALL ListPopActiveName()
8071
8072
Handle % ValuesVec(1:ngp) = MATMUL( BasisVec(1:ngp,1:n), F(1:n) )
8073
8074
CASE DEFAULT
8075
CALL Info('ListGetElementRealVec','This one implemented ONLY for "ListGetElementReal"',Level=3)
8076
CALL Fatal('ListGetElementRealVec','Impossible entry type for "'&
8077
//TRIM(Handle % Name)//'": '//I2S(ptr % TYPE))
8078
8079
END SELECT
8080
8081
END IF
8082
8083
END FUNCTION ListGetElementRealVec
8084
!------------------------------------------------------------------------------
8085
8086
8087
8088
8089
!------------------------------------------------------------------------------
8090
!> Gets a logical valued parameter in elements.
8091
!------------------------------------------------------------------------------
8092
FUNCTION ListGetElementLogical( Handle, Element, Found ) RESULT(Lvalue)
8093
!------------------------------------------------------------------------------
8094
TYPE(ValueHandle_t) :: Handle
8095
TYPE(Element_t), POINTER, OPTIONAL :: Element
8096
LOGICAL, OPTIONAL :: Found
8097
LOGICAL :: Lvalue
8098
!------------------------------------------------------------------------------
8099
TYPE(ValueList_t), POINTER :: List
8100
TYPE(Element_t), POINTER :: PElement
8101
LOGICAL :: ListSame, ListFound, LFound
8102
INTEGER :: id, BodyId
8103
!------------------------------------------------------------------------------
8104
8105
! If value is not present anywhere then return False
8106
IF( Handle % NotPresentAnywhere ) THEN
8107
IF(PRESENT(Found)) Found = .FALSE.
8108
Lvalue = Handle % DefLValue
8109
RETURN
8110
END IF
8111
8112
! If the value is known to be globally constant return it asap.
8113
IF( Handle % ConstantEverywhere ) THEN
8114
IF(PRESENT(Found)) Found = .TRUE.
8115
Lvalue = Handle % LValue
8116
RETURN
8117
END IF
8118
8119
! Find the pointer to the element, if not given
8120
IF( PRESENT( Element ) ) THEN
8121
PElement => Element
8122
ELSE
8123
PElement => CurrentModel % CurrentElement
8124
END IF
8125
8126
! We know by initialization the list entry type that the keyword has
8127
! Find the correct list to look the keyword in.
8128
! Bulk and boundary elements are treated separately.
8129
List => ElementHandleList( PElement, Handle, ListSame, ListFound )
8130
8131
IF( ListSame ) THEN
8132
IF( PRESENT( Found ) ) Found = Handle % Found
8133
LValue = Handle % LValue
8134
ELSE IF( ListFound ) THEN
8135
LValue = ListGetLogical( List, Handle % Name, LFound, UnfoundFatal = Handle % UnfoundFatal )
8136
Handle % LValue = LValue
8137
Handle % Found = LFound
8138
IF(PRESENT(Found)) Found = .TRUE.
8139
ELSE
8140
IF( Handle % UnfoundFatal ) THEN
8141
CALL Fatal('ListGetElementLogical','Could not find list for required keyword: '//TRIM(Handle % Name))
8142
END IF
8143
Lvalue = Handle % DefLValue
8144
Handle % Found = .FALSE.
8145
IF( PRESENT(Found) ) Found = .FALSE.
8146
END IF
8147
8148
END FUNCTION ListGetElementLogical
8149
!------------------------------------------------------------------------------
8150
8151
8152
!------------------------------------------------------------------------------
8153
!> Gets a integer valued parameter in elements.
8154
!------------------------------------------------------------------------------
8155
FUNCTION ListGetElementInteger( Handle, Element, Found ) RESULT(Ivalue)
8156
!------------------------------------------------------------------------------
8157
TYPE(ValueHandle_t) :: Handle
8158
TYPE(Element_t), POINTER, OPTIONAL :: Element
8159
LOGICAL, OPTIONAL :: Found
8160
INTEGER :: Ivalue
8161
!------------------------------------------------------------------------------
8162
TYPE(ValueList_t), POINTER :: List
8163
TYPE(Element_t), POINTER :: PElement
8164
LOGICAL :: ListSame, ListFound
8165
INTEGER :: id, BodyId
8166
!------------------------------------------------------------------------------
8167
8168
! If value is not present anywhere then return False
8169
IF( Handle % NotPresentAnywhere ) THEN
8170
IF(PRESENT(Found)) Found = .FALSE.
8171
Ivalue = Handle % DefIValue
8172
RETURN
8173
END IF
8174
8175
! If the value is known to be globally constant return it asap.
8176
IF( Handle % ConstantEverywhere ) THEN
8177
IF(PRESENT(Found)) Found = .TRUE.
8178
Ivalue = Handle % IValue
8179
RETURN
8180
END IF
8181
8182
! Find the pointer to the element, if not given
8183
IF( PRESENT( Element ) ) THEN
8184
PElement => Element
8185
ELSE
8186
PElement => CurrentModel % CurrentElement
8187
END IF
8188
8189
! We know by initialization the list entry type that the keyword has
8190
! Find the correct list to look the keyword in.
8191
! Bulk and boundary elements are treated separately.
8192
List => ElementHandleList( PElement, Handle, ListSame, ListFound )
8193
8194
IF( ListSame ) THEN
8195
IF( PRESENT( Found ) ) Found = Handle % Found
8196
IValue = Handle % IValue
8197
ELSE IF( ListFound ) THEN
8198
IValue = ListGetInteger( List, Handle % Name, Found, UnfoundFatal = Handle % UnfoundFatal )
8199
Handle % IValue = IValue
8200
IF(PRESENT(Found)) Handle % Found = Found
8201
ELSE
8202
IF( Handle % UnfoundFatal ) THEN
8203
CALL Fatal('ListGetElementInteger','Could not find list for required keyword: '//TRIM(Handle % Name))
8204
END IF
8205
Ivalue = Handle % DefIValue
8206
Handle % IValue = IValue
8207
IF( PRESENT(Found) ) THEN
8208
Found = .FALSE.
8209
Handle % Found = .FALSE.
8210
END IF
8211
END IF
8212
8213
8214
END FUNCTION ListGetElementInteger
8215
!------------------------------------------------------------------------------
8216
8217
8218
8219
!------------------------------------------------------------------------------
8220
!> Gets a string valued parameter in elements.
8221
!------------------------------------------------------------------------------
8222
FUNCTION ListGetElementString( Handle, Element, Found ) RESULT( CValue )
8223
!------------------------------------------------------------------------------
8224
TYPE(ValueHandle_t) :: Handle
8225
CHARACTER(LEN=MAX_NAME_LEN) :: CValue
8226
TYPE(Element_t), POINTER, OPTIONAL :: Element
8227
LOGICAL, OPTIONAL :: Found
8228
!------------------------------------------------------------------------------
8229
TYPE(ValueList_t), POINTER :: List
8230
TYPE(Element_t), POINTER :: PElement
8231
LOGICAL :: ListSame, ListFound
8232
INTEGER :: id, BodyId
8233
!------------------------------------------------------------------------------
8234
8235
! If value is not present anywhere then return False
8236
IF( Handle % NotPresentAnywhere ) THEN
8237
IF(PRESENT(Found)) Found = .FALSE.
8238
Cvalue = ' '
8239
RETURN
8240
END IF
8241
8242
! If the value is known to be globally constant return it asap.
8243
IF( Handle % ConstantEverywhere ) THEN
8244
IF(PRESENT(Found)) Found = .TRUE.
8245
Cvalue = TRIM(Handle % CValue)
8246
RETURN
8247
END IF
8248
8249
! Find the pointer to the element, if not given
8250
IF( PRESENT( Element ) ) THEN
8251
PElement => Element
8252
ELSE
8253
PElement => CurrentModel % CurrentElement
8254
END IF
8255
8256
! We know by initialization the list entry type that the keyword has
8257
! Find the correct list to look the keyword in.
8258
! Bulk and boundary elements are treated separately.
8259
List => ElementHandleList( PElement, Handle, ListSame, ListFound )
8260
8261
IF( ListSame ) THEN
8262
IF( PRESENT( Found ) ) Found = Handle % Found
8263
CValue = Handle % CValue(1:Handle % CValueLen)
8264
ELSE IF( ListFound ) THEN
8265
CValue = ListGetString( List, Handle % Name, Found, &
8266
UnfoundFatal = Handle % UnfoundFatal )
8267
Handle % CValue = TRIM(CValue)
8268
Handle % CValueLen = len_trim(CValue)
8269
IF(PRESENT(Found)) Handle % Found = Found
8270
ELSE
8271
IF( Handle % UnfoundFatal ) THEN
8272
CALL Fatal('ListGetElementString','Could not find list for required keyword: '//TRIM(Handle % Name))
8273
END IF
8274
Cvalue = ' '
8275
Handle % CValueLen = 0
8276
IF( PRESENT(Found) ) THEN
8277
Found = .FALSE.
8278
Handle % Found = .FALSE.
8279
END IF
8280
END IF
8281
8282
END FUNCTION ListGetElementString
8283
!------------------------------------------------------------------------------
8284
8285
8286
!------------------------------------------------------------------------------
8287
!> Is the keyword present somewhere
8288
!------------------------------------------------------------------------------
8289
FUNCTION ListGetElementSomewhere( Handle ) RESULT( Found )
8290
!------------------------------------------------------------------------------
8291
TYPE(ValueHandle_t) :: Handle
8292
LOGICAL :: Found
8293
!------------------------------------------------------------------------------
8294
Found = .NOT. ( Handle % NotPresentAnywhere )
8295
8296
END FUNCTION ListGetElementSomewhere
8297
!------------------------------------------------------------------------------
8298
8299
8300
8301
8302
!------------------------------------------------------------------------------
8303
!> Compares a string valued parameter in elements and return True if they are the same.
8304
!------------------------------------------------------------------------------
8305
FUNCTION ListCompareElementString( Handle, CValue2, Element, Found ) RESULT( SameString )
8306
!------------------------------------------------------------------------------
8307
TYPE(ValueHandle_t) :: Handle
8308
CHARACTER(LEN=*) :: CValue2
8309
TYPE(Element_t), POINTER, OPTIONAL :: Element
8310
LOGICAL, OPTIONAL :: Found
8311
LOGICAL :: SameString
8312
!------------------------------------------------------------------------------
8313
CHARACTER(LEN=MAX_NAME_LEN) :: CValue
8314
TYPE(ValueList_t), POINTER :: List
8315
TYPE(Element_t), POINTER :: PElement
8316
LOGICAL :: ListSame, ListFound, IntFound
8317
INTEGER :: id, BodyId
8318
!------------------------------------------------------------------------------
8319
8320
SameString = .FALSE.
8321
8322
! If value is not present anywhere then return False
8323
IF( Handle % NotPresentAnywhere ) THEN
8324
IF(PRESENT(Found)) Found = .FALSE.
8325
RETURN
8326
END IF
8327
8328
! If the value is known to be globally constant return it asap.
8329
IF( Handle % ConstantEverywhere ) THEN
8330
IF(PRESENT(Found)) Found = .TRUE.
8331
SameString = ( CValue2 == Handle % CValue(1:Handle % CValueLen) )
8332
RETURN
8333
END IF
8334
8335
! Find the pointer to the element, if not given
8336
IF( PRESENT( Element ) ) THEN
8337
PElement => Element
8338
ELSE
8339
PElement => CurrentModel % CurrentElement
8340
END IF
8341
8342
ListSame = .FALSE.
8343
ListFound = .FALSE.
8344
8345
! We know by initialization the list entry type that the keyword has
8346
! Find the correct list to look the keyword in.
8347
! Bulk and boundary elements are treated separately.
8348
List => ElementHandleList( PElement, Handle, ListSame, ListFound )
8349
8350
IF( ListSame ) THEN
8351
IF( PRESENT( Found ) ) Found = Handle % Found
8352
IF( Handle % Found ) THEN
8353
SameString = ( Handle % CValue(1:Handle % CValueLen) == CValue2 )
8354
END IF
8355
ELSE IF( ListFound ) THEN
8356
CValue = ListGetString( List, Handle % Name, IntFound, &
8357
UnfoundFatal = Handle % UnfoundFatal )
8358
Handle % Found = IntFound
8359
IF( IntFound ) THEN
8360
Handle % CValueLen = len_trim(CValue)
8361
Handle % CValue = CValue(1:Handle % CValueLen )
8362
SameString = (Handle % CValue(1:Handle % CValueLen) == CValue2 )
8363
END IF
8364
IF(PRESENT(Found)) Found = IntFound
8365
ELSE
8366
Handle % Cvalue = ' '
8367
Handle % CValueLen = 0
8368
Handle % Found = .FALSE.
8369
IF( PRESENT(Found) ) Found = .FALSE.
8370
END IF
8371
8372
END FUNCTION ListCompareElementString
8373
!------------------------------------------------------------------------------
8374
8375
8376
!------------------------------------------------------------------------------
8377
!> Initializes the variable handle in a similar manner as the keyword handle is
8378
!> initialized. This handle is more compact. Does not support p-fields or
8379
!> Hcurl & Hdiv fields yet.
8380
!------------------------------------------------------------------------------
8381
SUBROUTINE ListInitElementVariable( Handle, Name, USolver, UVariable, tStep, Found )
8382
!------------------------------------------------------------------------------
8383
TYPE(VariableHandle_t) :: Handle
8384
CHARACTER(LEN=*), OPTIONAL :: Name
8385
TYPE(Solver_t), OPTIONAL, TARGET :: USolver
8386
TYPE(Variable_t), OPTIONAL, TARGET :: UVariable
8387
INTEGER, OPTIONAL :: tStep
8388
LOGICAL, OPTIONAL :: Found
8389
8390
REAL(KIND=dp), POINTER :: Values(:)
8391
TYPE(Variable_t), POINTER :: Variable
8392
TYPE(Solver_t) , POINTER :: Solver
8393
TYPE(Element_t), POINTER :: Element
8394
8395
Handle % Variable => NULL()
8396
Handle % Values => NULL()
8397
Handle % Perm => NULL()
8398
Handle % Element => NULL()
8399
Handle % dofs = 0
8400
Handle % Found = .FALSE.
8401
8402
IF ( PRESENT(USolver) ) THEN
8403
Solver => USolver
8404
ELSE
8405
Solver => CurrentModel % Solver
8406
END IF
8407
8408
IF ( PRESENT(name) ) THEN
8409
Variable => VariableGet( Solver % Mesh % Variables, name )
8410
ELSE IF( PRESENT( UVariable ) ) THEN
8411
Variable => UVariable
8412
ELSE
8413
Variable => Solver % Variable
8414
END IF
8415
IF( PRESENT( Found ) ) Found = Handle % Found
8416
8417
IF ( .NOT. ASSOCIATED( Variable ) ) RETURN
8418
8419
Handle % Variable => Variable
8420
Handle % dofs = Variable % Dofs
8421
Handle % Found = .TRUE.
8422
8423
IF ( PRESENT(tStep) ) THEN
8424
IF ( tStep < 0 ) THEN
8425
IF ( ASSOCIATED(Variable % PrevValues) ) THEN
8426
IF ( -tStep<=SIZE(Variable % PrevValues,2)) &
8427
Handle % Values => Variable % PrevValues(:,-tStep)
8428
END IF
8429
END IF
8430
ELSE
8431
Handle % Values => Variable % Values
8432
END IF
8433
Handle % Perm => Variable % Perm
8434
8435
IF(PRESENT(Found)) Found = Handle % Found
8436
8437
END SUBROUTINE ListInitElementVariable
8438
!------------------------------------------------------------------------------
8439
8440
8441
!------------------------------------------------------------------------------
8442
!> Get a scalar field (e.g. potential or pressure) at the integration point.
8443
!> Works with different types of fields.
8444
!------------------------------------------------------------------------------
8445
FUNCTION ListGetElementScalarSolution( Handle, Basis, Element, Found, &
8446
GaussPoint, dof ) RESULT ( Val )
8447
8448
TYPE(VariableHandle_t) :: Handle
8449
REAL(KIND=dp), OPTIONAL :: Basis(:)
8450
TYPE( Element_t), POINTER, OPTIONAL :: Element
8451
INTEGER, OPTIONAL :: GaussPoint
8452
INTEGER, OPTIONAL :: dof
8453
LOGICAL, OPTIONAL :: Found
8454
REAL(KIND=dp) :: Val
8455
8456
TYPE( Element_t), POINTER :: pElement
8457
INTEGER :: i,j, k, n
8458
INTEGER, POINTER :: Indexes(:)
8459
LOGICAL :: SameElement
8460
8461
Val = 0.0_dp
8462
8463
IF( PRESENT( Found ) ) Found = .FALSE.
8464
8465
IF( .NOT. ASSOCIATED( Handle % Variable ) ) RETURN
8466
8467
! Find the pointer to the element, if not given
8468
IF( PRESENT( Element ) ) THEN
8469
PElement => Element
8470
ELSE
8471
PElement => CurrentModel % CurrentElement
8472
END IF
8473
8474
SameElement = ASSOCIATED( Handle % Element, pElement )
8475
IF( SameElement ) THEN
8476
IF( .NOT. Handle % ActiveElement ) RETURN
8477
ELSE
8478
Handle % Element => pElement
8479
END IF
8480
8481
IF( Handle % dofs > 1 ) THEN
8482
IF( .NOT. PRESENT( dof ) ) THEN
8483
CALL Fatal('ListGetElementScalarSolution','Argument "dof" is needed for vector fields!')
8484
END IF
8485
END IF
8486
8487
! If variable is defined on gauss points return that instead
8488
IF( Handle % Variable % TYPE == Variable_on_gauss_points ) THEN
8489
IF( .NOT. PRESENT( GaussPoint ) ) THEN
8490
CALL Fatal('ListGetElementScalarSolution','Argument "GaussPoint" required as an argument!')
8491
END IF
8492
8493
j = pElement % ElementIndex
8494
8495
IF( .NOT. SameElement ) THEN
8496
n = Handle % Perm(j+1) - Handle % Perm(j)
8497
Handle % ActiveElement = ( n > 0 )
8498
IF( n == 0 ) RETURN
8499
END IF
8500
8501
k = Handle % Perm(j) + GaussPoint
8502
8503
IF( Handle % Dofs == 1 ) THEN
8504
val = Handle % Values( k )
8505
ELSE
8506
val = Handle % Values( Handle % Dofs * (k-1) + dof )
8507
END IF
8508
8509
ELSE IF( Handle % Variable % TYPE == Variable_on_elements ) THEN
8510
j = Handle % Perm( pElement % ElementIndex )
8511
Handle % ActiveElement = ( j > 0 )
8512
8513
IF( j == 0 ) RETURN
8514
8515
IF( Handle % Dofs == 1 ) THEN
8516
val = Handle % Values( j )
8517
ELSE
8518
val = Handle % Values( Handle % Dofs * (j-1) + dof )
8519
END IF
8520
8521
ELSE
8522
IF( .NOT. PRESENT( Basis ) ) THEN
8523
CALL Fatal('ListGetElementScalarSolution',&
8524
'Argument "Basis" required for non gauss-point variable!')
8525
END IF
8526
8527
IF( .NOT. SameElement ) THEN
8528
IF( Handle % Variable % TYPE == Variable_on_nodes_on_elements ) THEN
8529
n = pElement % TYPE % NumberOfNodes
8530
Indexes => pElement % DGIndexes
8531
IF(.NOT. ASSOCIATED( Indexes ) ) THEN
8532
CALL Fatal('ListGetElementScalarSolution','DGIndexes not associated!')
8533
END IF
8534
ELSE
8535
n = pElement % TYPE % NumberOfNodes
8536
Indexes => pElement % NodeIndexes
8537
END IF
8538
8539
Handle % n = n
8540
8541
IF( ASSOCIATED( Handle % Perm ) ) THEN
8542
Handle % Indexes(1:n) = Handle % Perm( Indexes(1:n) )
8543
Handle % ActiveElement = ALL( Handle % Indexes(1:n) /= 0 )
8544
IF(.NOT. Handle % ActiveElement ) RETURN
8545
ELSE
8546
Handle % Indexes(1:n) = [(i,i=1,4)]
8547
Handle % ActiveElement = .TRUE.
8548
END IF
8549
END IF
8550
8551
n = Handle % n
8552
IF( Handle % Dofs == 1 ) THEN
8553
val = SUM( Basis(1:n) * Handle % Values( Handle % Indexes(1:n) ) )
8554
ELSE
8555
val = SUM( Basis(1:n) * Handle % Values( &
8556
Handle % dofs*(Handle % Indexes(1:n)-1)+dof ) )
8557
END IF
8558
8559
END IF
8560
8561
IF( PRESENT( Found ) ) Found = .TRUE.
8562
8563
END FUNCTION ListGetElementScalarSolution
8564
!------------------------------------------------------------------------------
8565
8566
!------------------------------------------------------------------------------
8567
!> Get a scalar field (e.g. potential or pressure) at the integration points.
8568
!> Works with different types of fields. Vectorized version.
8569
!------------------------------------------------------------------------------
8570
FUNCTION ListGetElementScalarSolutionVec( Handle, ngp, Basis, Element, Found, dof ) RESULT ( Vals )
8571
8572
TYPE(VariableHandle_t) :: Handle
8573
INTEGER :: ngp
8574
REAL(KIND=dp), OPTIONAL :: Basis(:,:)
8575
TYPE( Element_t), POINTER, OPTIONAL :: Element
8576
INTEGER, OPTIONAL :: dof
8577
LOGICAL, OPTIONAL :: Found
8578
REAL(KIND=dp), POINTER :: Vals(:)
8579
8580
TYPE( Element_t), POINTER :: pElement
8581
INTEGER :: i,j, k, n
8582
INTEGER, POINTER :: Indexes(:)
8583
8584
NULLIFY(Vals)
8585
8586
IF( PRESENT( Found ) ) Found = .FALSE.
8587
8588
IF( .NOT. ASSOCIATED( Handle % Variable ) ) RETURN
8589
8590
! Find the pointer to the element, if not given
8591
IF( PRESENT( Element ) ) THEN
8592
PElement => Element
8593
ELSE
8594
PElement => CurrentModel % CurrentElement
8595
END IF
8596
8597
IF( ASSOCIATED( Handle % Element, pElement ) ) THEN
8598
IF( Handle % ActiveElement ) THEN
8599
Vals => Handle % IpValues
8600
END IF
8601
IF( PRESENT( Found ) ) Found = Handle % ActiveElement
8602
RETURN
8603
ELSE
8604
Handle % Element => pElement
8605
END IF
8606
8607
IF( Handle % dofs > 1 ) THEN
8608
IF( .NOT. PRESENT( dof ) ) THEN
8609
CALL Fatal('ListGetElementScalarSolutionVec','Argument "dof" is needed for vector fields!')
8610
END IF
8611
END IF
8612
8613
IF( Handle % ipN < ngp ) THEN
8614
IF( Handle % ipN > 0 ) THEN
8615
DEALLOCATE( Handle % ipValues )
8616
END IF
8617
ALLOCATE( Handle % ipValues(ngp) )
8618
Handle % ipValues(1:ngp) = 0.0_dp
8619
Handle % ipN = ngp
8620
END IF
8621
8622
! If variable is defined on gauss points return that instead
8623
IF( Handle % Variable % TYPE == Variable_on_gauss_points ) THEN
8624
j = pElement % ElementIndex
8625
n = Handle % Perm(j+1) - Handle % Perm(j)
8626
Handle % ActiveElement = ( n > 0 )
8627
IF( n == 0 ) RETURN
8628
8629
IF( n /= ngp ) THEN
8630
CALL Fatal('ListGetElementScalarSolutionVec','Mismatch in number of Gauss points!')
8631
END IF
8632
8633
k = Handle % Perm(j)
8634
IF( Handle % Dofs == 1 ) THEN
8635
Handle % ipValues(1:ngp) = Handle % Values(k+1:k+ngp)
8636
ELSE
8637
Handle % ipValues(1:ngp) = Handle % Values(k+dof:k+ngp*Handle % Dofs:Handle % Dofs)
8638
END IF
8639
Vals => Handle % ipValues
8640
8641
ELSE IF( Handle % Variable % TYPE == Variable_on_elements ) THEN
8642
j = Handle % Perm( pElement % ElementIndex )
8643
Handle % ActiveElement = ( j > 0 )
8644
IF( j == 0 ) RETURN
8645
IF( Handle % Dofs == 1 ) THEN
8646
Handle % ipValues(1:ngp) = Handle % Values( j )
8647
ELSE
8648
Handle % ipValues(1:ngp) = Handle % Values( Handle % Dofs * (j-1) + dof )
8649
END IF
8650
Vals => Handle % ipValues
8651
8652
ELSE
8653
IF( .NOT. PRESENT( Basis ) ) THEN
8654
CALL Fatal('ListGetElementScalarSolutionVec',&
8655
'Argument "Basis" required for non gauss-point variable!')
8656
END IF
8657
8658
IF( Handle % Variable % TYPE == Variable_on_nodes_on_elements ) THEN
8659
n = pElement % TYPE % NumberOfNodes
8660
Indexes => pElement % DGIndexes
8661
IF(.NOT. ASSOCIATED( Indexes ) ) THEN
8662
CALL Fatal('ListGetElementScalarSolutionVec','DGIndexes not associated!')
8663
END IF
8664
ELSE
8665
n = pElement % TYPE % NumberOfNodes
8666
Indexes => pElement % NodeIndexes
8667
END IF
8668
8669
Handle % n = n
8670
8671
IF( ASSOCIATED( Handle % Perm ) ) THEN
8672
Handle % Indexes(1:n) = Handle % Perm( Indexes(1:n) )
8673
Handle % ActiveElement = ALL( Handle % Indexes(1:n) /= 0 )
8674
IF(.NOT. Handle % ActiveElement ) RETURN
8675
ELSE
8676
Handle % Indexes(1:n) = Indexes(1:n)
8677
Handle % ActiveElement = .TRUE.
8678
END IF
8679
8680
IF( Handle % Dofs == 1 ) THEN
8681
Handle % ipValues(1:ngp) = MATMUL(Basis(1:ngp,1:n),&
8682
Handle % Values( Handle % Indexes(1:n) ) )
8683
ELSE
8684
Handle % ipValues(1:ngp) = MATMUL(Basis(1:ngp,1:n),&
8685
Handle % Values( Handle % Dofs*( Handle % Indexes(1:n)-1)+dof ) )
8686
END IF
8687
Vals => Handle % ipValues
8688
END IF
8689
8690
IF( PRESENT( Found ) ) Found = ASSOCIATED( Vals )
8691
8692
END FUNCTION ListGetElementScalarSolutionVec
8693
!------------------------------------------------------------------------------
8694
8695
8696
!------------------------------------------------------------------------------
8697
!> Get a vector field (e.g. velocity or displacement) at the integration points.
8698
!> Works with different types of fields. Vectorized version.
8699
!------------------------------------------------------------------------------
8700
FUNCTION ListGetElementVectorSolutionVec( Handle, ngp, dim, Basis, Element, Found ) RESULT ( Vals )
8701
8702
TYPE(VariableHandle_t) :: Handle
8703
INTEGER :: ngp, dim
8704
REAL(KIND=dp), OPTIONAL :: Basis(:,:)
8705
TYPE( Element_t), POINTER, OPTIONAL :: Element
8706
LOGICAL, OPTIONAL :: Found
8707
REAL(KIND=dp), POINTER :: Vals(:,:)
8708
8709
TYPE( Element_t), POINTER :: pElement
8710
INTEGER :: i,j, k, n, dof
8711
INTEGER, POINTER :: Indexes(:)
8712
8713
NULLIFY(Vals)
8714
8715
IF( PRESENT( Found ) ) Found = .FALSE.
8716
8717
IF( .NOT. ASSOCIATED( Handle % Variable ) ) RETURN
8718
8719
! Find the pointer to the element, if not given
8720
IF( PRESENT( Element ) ) THEN
8721
PElement => Element
8722
ELSE
8723
PElement => CurrentModel % CurrentElement
8724
END IF
8725
8726
IF( ASSOCIATED( Handle % Element, pElement ) ) THEN
8727
IF( Handle % ActiveElement ) THEN
8728
Vals => Handle % IpValues3D
8729
END IF
8730
IF( PRESENT( Found ) ) Found = Handle % ActiveElement
8731
RETURN
8732
ELSE
8733
Handle % Element => pElement
8734
END IF
8735
8736
IF( Handle % ipN < ngp ) THEN
8737
IF( Handle % ipN > 0 ) THEN
8738
DEALLOCATE( Handle % ipValues3D )
8739
END IF
8740
ALLOCATE( Handle % ipValues3D(ngp,Handle % dofs) )
8741
Handle % ipValues3D(1:ngp,1:Handle % Dofs) = 0.0_dp
8742
Handle % ipN = ngp
8743
END IF
8744
8745
! If variable is defined on gauss points return that instead
8746
IF( Handle % Variable % TYPE == Variable_on_gauss_points ) THEN
8747
j = pElement % ElementIndex
8748
n = Handle % Perm(j+1) - Handle % Perm(j)
8749
Handle % ActiveElement = ( n > 0 )
8750
IF( n == 0 ) RETURN
8751
8752
IF( n /= ngp ) THEN
8753
CALL Fatal('ListGetElementVectorSolutionVec','Mismatch in number of Gauss points!')
8754
END IF
8755
8756
k = Handle % Perm(j)
8757
DO dof=1,MIN(Handle % dofs,dim)
8758
Handle % ipValues3D(1:ngp,dof) = Handle % Values(k+dof:k+ngp*Handle % Dofs:Handle % Dofs)
8759
END DO
8760
Vals => Handle % ipValues3D
8761
8762
ELSE IF( Handle % Variable % TYPE == Variable_on_elements ) THEN
8763
j = Handle % Perm( pElement % ElementIndex )
8764
Handle % ActiveElement = ( j > 0 )
8765
IF( j == 0 ) RETURN
8766
8767
DO dof=1,MIN(Handle % dofs,dim)
8768
Handle % ipValues3D(1:ngp,dof) = Handle % Values( Handle % Dofs * (j-1) + dof )
8769
END DO
8770
Vals => Handle % ipValues3D
8771
8772
ELSE
8773
IF( .NOT. PRESENT( Basis ) ) THEN
8774
CALL Fatal('ListGetElementVectorSolutionVec',&
8775
'Argument "Basis" required for non gauss-point variable!')
8776
END IF
8777
8778
IF( Handle % Variable % TYPE == Variable_on_nodes_on_elements ) THEN
8779
n = pElement % TYPE % NumberOfNodes
8780
Indexes => pElement % DGIndexes
8781
IF(.NOT. ASSOCIATED( Indexes ) ) THEN
8782
CALL Fatal('ListGetElementVectorSolutionVec','DGIndexes not associated!')
8783
END IF
8784
ELSE
8785
n = pElement % TYPE % NumberOfNodes
8786
Indexes => pElement % NodeIndexes
8787
END IF
8788
8789
Handle % n = n
8790
8791
IF( ASSOCIATED( Handle % Perm ) ) THEN
8792
Handle % Indexes(1:n) = Handle % Perm( Indexes(1:n) )
8793
Handle % ActiveElement = ALL( Handle % Indexes(1:n) /= 0 )
8794
IF(.NOT. Handle % ActiveElement ) RETURN
8795
ELSE
8796
Handle % Indexes(1:n) = Indexes(1:n)
8797
Handle % ActiveElement = .TRUE.
8798
END IF
8799
8800
DO dof=1,MIN(Handle % dofs,dim)
8801
Handle % ipValues3D(1:ngp,dof) = MATMUL(Basis(1:ngp,1:n),&
8802
Handle % Values( Handle % Dofs*( Handle % Indexes(1:n)-1)+dof ) )
8803
END DO
8804
Vals => Handle % ipValues3D
8805
END IF
8806
8807
IF( PRESENT( Found ) ) Found = ASSOCIATED( Vals )
8808
8809
END FUNCTION ListGetElementVectorSolutionVec
8810
!------------------------------------------------------------------------------
8811
8812
8813
!------------------------------------------------------------------------------
8814
!> Get a vector field (e.g. velocity or displacement) at the integration point.
8815
!> Works with different types of fields.
8816
!------------------------------------------------------------------------------
8817
FUNCTION ListGetElementVectorSolution( Handle, Basis, Element, Found, GaussPoint, &
8818
dofs ) &
8819
RESULT ( Val3D )
8820
8821
TYPE(VariableHandle_t) :: Handle
8822
REAL(KIND=dp), OPTIONAL :: Basis(:)
8823
TYPE( Element_t), POINTER, OPTIONAL :: Element
8824
INTEGER, OPTIONAL :: GaussPoint
8825
INTEGER, OPTIONAL :: dofs
8826
LOGICAL, OPTIONAL :: Found
8827
REAL(KIND=dp) :: Val3D(3)
8828
8829
INTEGER :: dof, Ldofs
8830
8831
Val3D = 0.0_dp
8832
8833
IF( .NOT. ASSOCIATED( Handle % Variable ) ) THEN
8834
IF(PRESENT(Found)) Found = .FALSE.
8835
RETURN
8836
END IF
8837
8838
IF( PRESENT( dofs ) ) THEN
8839
Ldofs = dofs
8840
ELSE
8841
Ldofs = MIN( 3, Handle % Dofs )
8842
END IF
8843
8844
DO dof = 1, Ldofs
8845
Val3D(dof) = ListGetElementScalarSolution( Handle, Basis, Element, Found, &
8846
GaussPoint, dof )
8847
IF( .NOT. Handle % ActiveElement ) RETURN
8848
END DO
8849
8850
END FUNCTION ListGetElementVectorSolution
8851
8852
8853
8854
!------------------------------------------------------------------------------
8855
!> Gets a constant real array from the list by its name.
8856
!------------------------------------------------------------------------------
8857
RECURSIVE FUNCTION ListGetConstRealArray( List,Name,Found,UnfoundFatal ) RESULT( F )
8858
!------------------------------------------------------------------------------
8859
TYPE(ValueList_t), POINTER :: List
8860
CHARACTER(LEN=*) :: Name
8861
LOGICAL, OPTIONAL :: Found, UnfoundFatal
8862
!------------------------------------------------------------------------------
8863
REAL(KIND=dp), POINTER :: F(:,:)
8864
INTEGER :: i,j,n,m
8865
TYPE(ValueListEntry_t), POINTER :: ptr
8866
!------------------------------------------------------------------------------
8867
NULLIFY( F )
8868
ptr => ListFind(List,Name,Found)
8869
IF (.NOT.ASSOCIATED(ptr) ) THEN
8870
IF(PRESENT(UnfoundFatal)) THEN
8871
IF(UnfoundFatal) THEN
8872
CALL Fatal("ListGetConstRealArray", "Failed to find: "//TRIM(Name) )
8873
END IF
8874
END IF
8875
RETURN
8876
END IF
8877
8878
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
8879
CALL Fatal( 'ListGetConstRealArray', 'Value type for property ['//TRIM(Name)// &
8880
'] not used consistently.')
8881
END IF
8882
8883
n = SIZE( ptr % FValues,1 )
8884
m = SIZE( ptr % FValues,2 )
8885
8886
F => ptr % FValues(:,:,1)
8887
8888
IF ( ptr % PROCEDURE /= 0 ) THEN
8889
CALL ListPushActiveName(name)
8890
DO i=1,n
8891
DO j=1,m
8892
F(i,j) = ExecConstRealFunction( ptr % PROCEDURE,CurrentModel,0.0d0,0.0d0,0.0d0 )
8893
END DO
8894
END DO
8895
CALL ListPopActiveName()
8896
END IF
8897
END FUNCTION ListGetConstRealArray
8898
!------------------------------------------------------------------------------
8899
8900
8901
!------------------------------------------------------------------------------
8902
!> Gets an 1D constant real array from the list by its name.
8903
!------------------------------------------------------------------------------
8904
RECURSIVE FUNCTION ListGetConstRealArray1( List,Name,Found,UnfoundFatal ) RESULT( F )
8905
!------------------------------------------------------------------------------
8906
TYPE(ValueList_t), POINTER :: List
8907
CHARACTER(LEN=*) :: Name
8908
LOGICAL, OPTIONAL :: Found, UnfoundFatal
8909
!------------------------------------------------------------------------------
8910
REAL(KIND=dp), POINTER :: F(:)
8911
INTEGER :: i,j,n,m
8912
TYPE(ValueListEntry_t), POINTER :: ptr
8913
!------------------------------------------------------------------------------
8914
NULLIFY( F )
8915
ptr => ListFind(List,Name,Found)
8916
IF (.NOT.ASSOCIATED(ptr) ) THEN
8917
IF(PRESENT(UnfoundFatal)) THEN
8918
IF(UnfoundFatal) THEN
8919
CALL Fatal("ListGetConstRealArray1","Failed to find: "//TRIM(Name))
8920
END IF
8921
END IF
8922
RETURN
8923
END IF
8924
8925
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
8926
CALL Fatal( 'ListGetConstRealArray1', 'Value type for property ['//TRIM(Name)// &
8927
'] not used consistently.')
8928
END IF
8929
8930
n = SIZE( ptr % FValues,1 )
8931
m = SIZE( ptr % FValues,2 )
8932
IF( m > 1 ) THEN
8933
CALL Warn('ListGetConstRealArray1','The routine is designed for 1D arrays!')
8934
END IF
8935
8936
F => ptr % FValues(:,1,1)
8937
8938
END FUNCTION ListGetConstRealArray1
8939
!------------------------------------------------------------------------------
8940
8941
8942
8943
!------------------------------------------------------------------------------
8944
!> Gets a real array from the list by its name,
8945
!------------------------------------------------------------------------------
8946
RECURSIVE SUBROUTINE ListGetRealArray( List,Name,F,ni,NodeIndexes,Found, UnfoundFatal)
8947
!------------------------------------------------------------------------------
8948
TYPE(ValueList_t), POINTER :: List
8949
CHARACTER(LEN=*) :: Name
8950
LOGICAL, OPTIONAL :: Found, UnfoundFatal
8951
INTEGER :: ni,NodeIndexes(:)
8952
REAL(KIND=dp), POINTER :: F(:,:,:), G(:,:)
8953
!------------------------------------------------------------------------------
8954
TYPE(ValueListEntry_t), POINTER :: ptr
8955
8956
TYPE(Variable_t), POINTER :: Variable, CVar, TVar
8957
8958
REAL(KIND=dp) :: T(MAX_FNC)
8959
LOGICAL :: AllGlobal
8960
INTEGER :: i,j,k,nlen,n,m,k1,l
8961
!------------------------------------------------------------------------------
8962
ptr => ListFind(List,Name,Found)
8963
IF ( .NOT.ASSOCIATED(ptr) ) THEN
8964
IF(PRESENT(UnfoundFatal)) THEN
8965
IF(UnfoundFatal) THEN
8966
CALL Fatal("ListGetConstRealArray","Failed to find: "//TRIM(Name))
8967
END IF
8968
END IF
8969
RETURN
8970
END IF
8971
8972
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
8973
CALL Fatal( 'ListGetRealArray', &
8974
'Value type for property > '// TRIM(Name) // '< not used consistently.')
8975
END IF
8976
8977
n = SIZE(ptr % FValues,1)
8978
m = SIZE(ptr % FValues,2)
8979
8980
IF ( .NOT.ASSOCIATED( F ) ) THEN
8981
ALLOCATE( F(n,m,ni) )
8982
ELSE IF ( SIZE(F,1)/=n.OR.SIZE(F,2)/=n.OR.SIZE(F,3)/=ni ) THEN
8983
DEALLOCATE( F )
8984
ALLOCATE( F(n,m,ni) )
8985
END IF
8986
8987
8988
SELECT CASE(ptr % TYPE)
8989
CASE ( LIST_TYPE_CONSTANT_TENSOR )
8990
DO i=1,ni
8991
F(:,:,i) = ptr % Coeff * ptr % FValues(:,:,1)
8992
END DO
8993
8994
IF ( ptr % PROCEDURE /= 0 ) THEN
8995
CALL ListPushActiveName(name)
8996
DO i=1,n
8997
DO j=1,m
8998
F(i,j,1) = ptr % Coeff * &
8999
ExecConstRealFunction( ptr % PROCEDURE, &
9000
CurrentModel, 0.0_dp, 0.0_dp, 0.0_dp )
9001
END DO
9002
END DO
9003
CALL ListPopActiveName()
9004
END IF
9005
9006
9007
CASE( LIST_TYPE_VARIABLE_TENSOR,LIST_TYPE_VARIABLE_TENSOR_STR )
9008
9009
CALL ListPushActiveName(name)
9010
DO i=1,ni
9011
k = NodeIndexes(i)
9012
CALL ListParseStrToValues( Ptr % DependName, Ptr % DepNameLen, k, Name, T, j, AllGlobal)
9013
IF ( ANY(T(1:j)==HUGE(1._dP)) ) CYCLE
9014
9015
IF ( ptr % TYPE==LIST_TYPE_VARIABLE_TENSOR_STR) THEN
9016
IF ( .NOT. ptr % LuaFun ) THEN
9017
F(1:n,1:m,i) = GetMatcRealArray(ptr % Cvalue,n,m,j,T)
9018
ELSE
9019
call ElmerEvalLuaT(LuaState, ptr, T, F(:,:,i), j)
9020
END IF
9021
ELSE IF ( ptr % PROCEDURE /= 0 ) THEN
9022
G => F(:,:,i)
9023
CALL ExecRealArrayFunction( ptr % PROCEDURE, CurrentModel, &
9024
NodeIndexes(i), T, G )
9025
ELSE
9026
DO j=1,n
9027
DO k=1,m
9028
F(j,k,i) = InterpolateCurve(ptr % TValues, ptr % FValues(j,k,:), &
9029
T(1), ptr % CubicCoeff )
9030
END DO
9031
END DO
9032
END IF
9033
IF( AllGlobal ) EXIT
9034
END DO
9035
CALL ListPopActiveName()
9036
9037
IF( AllGlobal ) THEN
9038
DO i=2,ni
9039
DO j=1,n
9040
DO k=1,m
9041
F(j,k,i) = F(j,k,1)
9042
END DO
9043
END DO
9044
END DO
9045
END IF
9046
9047
IF( ABS( ptr % Coeff - 1.0_dp ) > EPSILON( ptr % Coeff ) ) THEN
9048
F = ptr % Coeff * F
9049
END IF
9050
9051
CASE DEFAULT
9052
F = 0.0d0
9053
DO i=1,n
9054
IF ( PRESENT( Found ) ) THEN
9055
F(i,1,:) = ListGetReal( List,Name,ni,NodeIndexes,Found )
9056
ELSE
9057
F(i,1,:) = ListGetReal( List,Name,ni,NodeIndexes )
9058
END IF
9059
END DO
9060
END SELECT
9061
!------------------------------------------------------------------------------
9062
END SUBROUTINE ListGetRealArray
9063
!------------------------------------------------------------------------------
9064
9065
!------------------------------------------------------------------------------
9066
!> Gets a real vector from the list by its name
9067
!------------------------------------------------------------------------------
9068
RECURSIVE SUBROUTINE ListGetRealVector( List,Name,F,ni,NodeIndexes,Found )
9069
!------------------------------------------------------------------------------
9070
TYPE(ValueList_t), POINTER :: List
9071
CHARACTER(LEN=*) :: Name
9072
LOGICAL, OPTIONAL :: Found
9073
INTEGER :: ni,NodeIndexes(:)
9074
REAL(KIND=dp), TARGET :: F(:,:)
9075
!------------------------------------------------------------------------------
9076
TYPE(ValueListEntry_t), POINTER :: ptr
9077
9078
TYPE(Variable_t), POINTER :: Variable, CVar, TVar
9079
9080
REAL(KIND=dp), ALLOCATABLE :: G(:,:)
9081
REAL(KIND=dp) :: T(MAX_FNC)
9082
REAL(KIND=dp), POINTER :: RotMatrix(:,:)
9083
INTEGER :: i,j,k,nlen,n,m,k1,S1,S2,l, cnt
9084
LOGICAL :: AllGlobal, lFound, AnyFound
9085
!------------------------------------------------------------------------------
9086
ptr => ListFind(List,Name,lFound)
9087
IF ( .NOT.ASSOCIATED(ptr) ) THEN
9088
IF(PRESENT(Found)) Found = .FALSE.
9089
AnyFound = .FALSE.
9090
DO i=1,SIZE(F,1)
9091
F(i,1:ni) = ListGetReal(List,TRIM(Name)//' '//I2S(i),ni,NodeIndexes,lFound)
9092
AnyFound = AnyFound.OR.lFound
9093
END DO
9094
IF(PRESENT(Found)) THEN
9095
Found = AnyFound
9096
ELSE IF(.NOT.AnyFound) THEN
9097
CALL Warn( 'ListFind', 'Requested property ['//TRIM(Name)//'] not found')
9098
END IF
9099
IF( .NOT. AnyFound ) RETURN
9100
GOTO 200
9101
ELSE
9102
Found = lFound
9103
END IF
9104
9105
F = 0._dp
9106
cnt = 0
9107
ALLOCATE(G(SIZE(F,1),SIZE(F,2)))
9108
9109
100 CONTINUE
9110
9111
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
9112
CALL Fatal( 'ListGetRealVector', &
9113
'Value type for property > '// TRIM(Name) // '< not used consistently.')
9114
END IF
9115
9116
n = SIZE(ptr % FValues,1)
9117
9118
SELECT CASE(ptr % TYPE)
9119
CASE ( LIST_TYPE_CONSTANT_TENSOR )
9120
DO i=1,n
9121
G(:,i) = ptr % Coeff * ptr % FValues(:,1,1)
9122
END DO
9123
9124
IF ( ptr % PROCEDURE /= 0 ) THEN
9125
CALL ListPushActiveName(name)
9126
DO i=1,n
9127
F(i,1) = ptr % Coeff * &
9128
ExecConstRealFunction( ptr % PROCEDURE, &
9129
CurrentModel, 0.0_dp, 0.0_dp, 0.0_dp )
9130
END DO
9131
CALL ListPopActiveName()
9132
END IF
9133
9134
CASE( LIST_TYPE_VARIABLE_TENSOR,LIST_TYPE_VARIABLE_TENSOR_STR )
9135
9136
CALL ListPushActiveName(name)
9137
DO i=1,ni
9138
k = NodeIndexes(i)
9139
CALL ListParseStrToValues( Ptr % DependName, Ptr % DepNameLen, k, Name, T, j, AllGlobal)
9140
IF ( ANY(T(1:j)==HUGE(1._dP)) ) CYCLE
9141
9142
IF ( ptr % TYPE==LIST_TYPE_VARIABLE_TENSOR_STR) THEN
9143
IF ( .NOT. ptr % LuaFun ) THEN
9144
G(1:n,i) = GetMatcRealVector(ptr % Cvalue,n,j,T)
9145
ELSE
9146
CALL ElmerEvalLuaV(LuaState, ptr, T, G(:,i), j)
9147
END IF
9148
ELSE IF ( ptr % PROCEDURE /= 0 ) THEN
9149
CALL ExecRealVectorFunction( ptr % PROCEDURE, CurrentModel, &
9150
NodeIndexes(i), T, G(:,i) )
9151
ELSE
9152
DO k=1,n
9153
G(k,i) = InterpolateCurve(ptr % TValues, &
9154
ptr % FValues(k,1,:), T(MIN(j,k)), ptr % CubicCoeff )
9155
END DO
9156
END IF
9157
9158
IF( AllGlobal ) EXIT
9159
END DO
9160
CALL ListPopActiveName()
9161
9162
IF( AllGlobal ) THEN
9163
DO i=2,ni
9164
DO j=1,n
9165
G(j,i) = G(j,1)
9166
END DO
9167
END DO
9168
END IF
9169
9170
IF( ABS( ptr % Coeff - 1.0_dp ) > EPSILON( ptr % Coeff ) ) THEN
9171
G = ptr % Coeff * G
9172
END IF
9173
9174
CASE DEFAULT
9175
G = 0.0d0
9176
DO i=1,n
9177
IF ( PRESENT( Found ) ) THEN
9178
G(i,1:ni) = ListGetReal( List,Name,ni,NodeIndexes,Found )
9179
ELSE
9180
G(i,1:ni) = ListGetReal( List,Name,ni,NodeIndexes )
9181
END IF
9182
END DO
9183
END SELECT
9184
9185
9186
F = F + G
9187
cnt = cnt + 1
9188
ptr => ListFind(List,Name//'{'//I2S(cnt)//'}',lFound)
9189
IF(ASSOCIATED(ptr)) GOTO 100
9190
9191
200 IF( ListGetLogical( List, Name//' Property Rotate', lFound ) ) THEN
9192
RotMatrix => ListGetConstRealArray( List,'Property Rotation Matrix',lFound )
9193
IF( .NOT. ASSOCIATED( RotMatrix ) ) THEN
9194
CALL Fatal('ListGetRealVector','Property rotation matrix not given for: '//TRIM(Name))
9195
END IF
9196
IF( SIZE(F,1) /= 3 ) THEN
9197
CALL Fatal('ListGetRealVector','Property may be rotated only with three components!')
9198
END IF
9199
DO i = 1,SIZE(F,2)
9200
F(1:3,i) = MATMUL( RotMatrix, F(1:3,i) )
9201
END DO
9202
END IF
9203
9204
9205
!------------------------------------------------------------------------------
9206
END SUBROUTINE ListGetRealVector
9207
!------------------------------------------------------------------------------
9208
9209
9210
!------------------------------------------------------------------------------
9211
!> Gets a real derivative from. This is only available for tables with dependencies.
9212
!------------------------------------------------------------------------------
9213
RECURSIVE FUNCTION ListGetDerivValue(List,Name,N,NodeIndexes,dT) RESULT(F)
9214
!------------------------------------------------------------------------------
9215
TYPE(ValueList_t), POINTER :: List
9216
CHARACTER(LEN=*) :: Name
9217
INTEGER :: N,NodeIndexes(:)
9218
REAL(KIND=dp), OPTIONAL :: dT
9219
REAL(KIND=dp) :: F(N)
9220
!------------------------------------------------------------------------------
9221
TYPE(Variable_t), POINTER :: Variable
9222
TYPE(ValueListEntry_t), POINTER :: ptr
9223
INTEGER :: i,k,l
9224
REAL(KIND=dp) :: T,T1(1),T2(1),F1,F2
9225
!------------------------------------------------------------------------------
9226
9227
F = 0.0D0
9228
ptr => ListFind(List,Name)
9229
9230
9231
IF ( .NOT.ASSOCIATED(ptr) ) RETURN
9232
9233
9234
SELECT CASE(ptr % TYPE)
9235
CASE( LIST_TYPE_VARIABLE_SCALAR )
9236
9237
IF ( ptr % PROCEDURE /= 0 ) THEN
9238
IF( .NOT. PRESENT( dT ) ) THEN
9239
CALL Fatal('ListGetDerivValue','Numerical derivative of function requires dT')
9240
END IF
9241
Variable => VariableGet( CurrentModel % Variables,ptr % DependName )
9242
IF( .NOT. ASSOCIATED( Variable ) ) THEN
9243
CALL Fatal('ListGetDeriveValue','Cannot derivate with variable: '//TRIM(ptr % DependName))
9244
END IF
9245
9246
DO i=1,n
9247
k = NodeIndexes(i)
9248
IF ( ASSOCIATED(Variable % Perm) ) k = Variable % Perm(k)
9249
IF ( k > 0 ) THEN
9250
T = Variable % Values(k)
9251
T1(1) = T + 0.5_dp * dT
9252
T2(1) = T - 0.5_dp * dT
9253
F1 = ExecRealFunction( ptr % PROCEDURE,CurrentModel, NodeIndexes(i), T1 )
9254
F2 = ExecRealFunction( ptr % PROCEDURE,CurrentModel, NodeIndexes(i), T2 )
9255
F(i) = ptr % Coeff * ( F1 - F2 ) / dT
9256
END IF
9257
END DO
9258
9259
ELSE
9260
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
9261
CALL Fatal( 'ListGetDerivValue', &
9262
'Value type for property > '// TRIM(Name) // '< not used consistently.')
9263
END IF
9264
Variable => VariableGet( CurrentModel % Variables,ptr % DependName )
9265
IF( .NOT. ASSOCIATED( Variable ) ) THEN
9266
CALL Fatal('ListGetDeriveValue','Cannot derivate with variable: '//TRIM(ptr % DependName))
9267
END IF
9268
DO i=1,n
9269
k = NodeIndexes(i)
9270
IF ( ASSOCIATED(Variable % Perm) ) k = Variable % Perm(k)
9271
IF ( k > 0 ) THEN
9272
T = Variable % Values(k)
9273
F(i) = ptr % Coeff * &
9274
DerivateCurve(ptr % TValues,ptr % FValues(1,1,:), &
9275
T, ptr % CubicCoeff )
9276
END IF
9277
END DO
9278
END IF
9279
9280
9281
CASE DEFAULT
9282
CALL Fatal( 'ListGetDerivValue', &
9283
'No automated derivation possible for > '//TRIM(Name)//' <' )
9284
9285
END SELECT
9286
9287
9288
END FUNCTION ListGetDerivValue
9289
!------------------------------------------------------------------------------
9290
9291
9292
!------------------------------------------------------------------------------
9293
!> Given the body of a keyword find the 1st free keyword in the list structure.
9294
!> The intended use for this is in Solver_init to declare exported variables
9295
!> without the risk of running over some existing ones.
9296
!------------------------------------------------------------------------------
9297
FUNCTION NextFreeKeyword(keyword0,List) RESULT (Keyword)
9298
9299
CHARACTER(LEN=*) :: Keyword0
9300
TYPE(ValueList_t), POINTER :: List
9301
CHARACTER(:), ALLOCATABLE :: Keyword
9302
INTEGER :: No
9303
9304
DO No = 1, 9999
9305
Keyword = TRIM(Keyword0)//' '//I2S(No)
9306
IF( .NOT. ListCheckPresent(List,Keyword)) EXIT
9307
END DO
9308
9309
!------------------------------------------------------------------------------
9310
END FUNCTION NextFreeKeyword
9311
!------------------------------------------------------------------------------
9312
9313
9314
!------------------------------------------------------------------------------
9315
!> Check if the keyword is present in any boundary condition.
9316
!------------------------------------------------------------------------------
9317
FUNCTION ListCheckPresentAnyBC( Model, Name, ValueLst ) RESULT(Found)
9318
!------------------------------------------------------------------------------
9319
TYPE(Model_t) :: Model
9320
CHARACTER(LEN=*) :: Name
9321
TYPE(ValueList_t), POINTER, OPTIONAL :: ValueLst
9322
LOGICAL :: Found
9323
INTEGER :: bc
9324
9325
Found = .FALSE.
9326
IF(PRESENT(ValueLst)) ValueLst => NULL()
9327
DO bc = 1,Model % NumberOfBCs
9328
Found = ListCheckPresent( Model % BCs(bc) % Values, Name )
9329
IF( Found ) THEN
9330
IF(PRESENT(ValueLst)) ValueLst => Model % BCs(bc) % Values
9331
EXIT
9332
END IF
9333
END DO
9334
!------------------------------------------------------------------------------
9335
END FUNCTION ListCheckPresentAnyBC
9336
!------------------------------------------------------------------------------
9337
9338
!------------------------------------------------------------------------------
9339
!> Check if the keyword is present in any boundary condition.
9340
!------------------------------------------------------------------------------
9341
FUNCTION ListCheckPresentAnyIC( Model, Name, ValueLst ) RESULT(Found)
9342
!------------------------------------------------------------------------------
9343
TYPE(Model_t) :: Model
9344
CHARACTER(LEN=*) :: Name
9345
TYPE(ValueList_t), POINTER, OPTIONAL :: ValueLst
9346
LOGICAL :: Found
9347
INTEGER :: ic
9348
9349
Found = .FALSE.
9350
IF(PRESENT(ValueLst)) ValueLst => NULL()
9351
DO ic = 1,Model % NumberOfICs
9352
Found = ListCheckPresent( Model % ICs(ic) % Values, Name )
9353
IF( Found ) THEN
9354
IF(PRESENT(ValueLst)) ValueLst => Model % ICs(ic) % Values
9355
EXIT
9356
END IF
9357
END DO
9358
!------------------------------------------------------------------------------
9359
END FUNCTION ListCheckPresentAnyIC
9360
!------------------------------------------------------------------------------
9361
9362
!------------------------------------------------------------------------------
9363
!> Check if the keyword is True in any boundary condition.
9364
!------------------------------------------------------------------------------
9365
FUNCTION ListGetLogicalAnyBC( Model, Name ) RESULT(Found)
9366
!------------------------------------------------------------------------------
9367
TYPE(Model_t) :: Model
9368
CHARACTER(LEN=*) :: Name
9369
LOGICAL :: Found, GotIt
9370
INTEGER :: bc
9371
9372
Found = .FALSE.
9373
DO bc = 1,Model % NumberOfBCs
9374
Found = ListgetLogical( Model % BCs(bc) % Values, Name, GotIt )
9375
IF( Found ) EXIT
9376
END DO
9377
!------------------------------------------------------------------------------
9378
END FUNCTION ListGetLogicalAnyBC
9379
!------------------------------------------------------------------------------
9380
9381
9382
!------------------------------------------------------------------------------
9383
!> Check if the keyword is present in any body.
9384
!------------------------------------------------------------------------------
9385
FUNCTION ListCheckPresentAnyBody( Model, Name, ValueLst ) RESULT(Found)
9386
!------------------------------------------------------------------------------
9387
TYPE(Model_t) :: Model
9388
CHARACTER(LEN=*) :: Name
9389
TYPE(ValueList_t), POINTER, OPTIONAL :: ValueLst
9390
LOGICAL :: Found
9391
INTEGER :: body
9392
9393
Found = .FALSE.
9394
IF(PRESENT(ValueLst)) ValueLst => NULL()
9395
DO body = 1,Model % NumberOfBodies
9396
Found = ListCheckPresent( Model % Bodies(body) % Values, Name )
9397
IF( Found ) THEN
9398
IF(PRESENT(ValueLst)) ValueLst => Model % Bodies(body) % Values
9399
EXIT
9400
END IF
9401
END DO
9402
!------------------------------------------------------------------------------
9403
END FUNCTION ListCheckPresentAnyBody
9404
!------------------------------------------------------------------------------
9405
9406
!------------------------------------------------------------------------------
9407
!> Check if the keyword is true in any body.
9408
!------------------------------------------------------------------------------
9409
FUNCTION ListGetLogicalAnyBody( Model, Name ) RESULT(Found)
9410
!------------------------------------------------------------------------------
9411
TYPE(Model_t) :: Model
9412
CHARACTER(LEN=*) :: Name
9413
LOGICAL :: Found
9414
INTEGER :: body
9415
LOGICAL :: GotIt
9416
9417
Found = .FALSE.
9418
DO body = 1,Model % NumberOfBodies
9419
Found = ListGetLogical( Model % Bodies(body) % Values, Name, GotIt )
9420
IF( Found ) EXIT
9421
END DO
9422
!------------------------------------------------------------------------------
9423
END FUNCTION ListGetLogicalAnyBody
9424
!------------------------------------------------------------------------------
9425
9426
9427
!------------------------------------------------------------------------------
9428
!> Check if the keyword is true in any body.
9429
!------------------------------------------------------------------------------
9430
FUNCTION ListGetCRealAnyBody( Model, Name, Found ) RESULT( F )
9431
!------------------------------------------------------------------------------
9432
TYPE(Model_t) :: Model
9433
CHARACTER(LEN=*) :: Name
9434
LOGICAL, OPTIONAL :: Found
9435
REAL(KIND=dp) :: F
9436
9437
INTEGER :: body
9438
LOGICAL :: GotIt
9439
9440
F = 0.0_dp
9441
GotIt = .FALSE.
9442
DO body = 1,Model % NumberOfBodies
9443
F = ListGetCReal( Model % Bodies(body) % Values, Name, GotIt )
9444
IF( GotIt ) EXIT
9445
END DO
9446
9447
IF( PRESENT( Found ) ) Found = GotIt
9448
9449
!------------------------------------------------------------------------------
9450
END FUNCTION ListGetCRealAnyBody
9451
!------------------------------------------------------------------------------
9452
9453
!------------------------------------------------------------------------------
9454
!> Check if the keyword is present in any body force.
9455
!------------------------------------------------------------------------------
9456
FUNCTION ListCheckPresentAnyBodyForce( Model, Name, ValueLst ) RESULT(Found)
9457
!------------------------------------------------------------------------------
9458
TYPE(Model_t) :: Model
9459
CHARACTER(LEN=*) :: Name
9460
TYPE(ValueList_t), POINTER, OPTIONAL :: ValueLst
9461
LOGICAL :: Found
9462
INTEGER :: bf
9463
9464
Found = .FALSE.
9465
IF(PRESENT(ValueLst)) ValueLst => NULL()
9466
DO bf = 1,Model % NumberOfBodyForces
9467
Found = ListCheckPresent( Model % BodyForces(bf) % Values, Name )
9468
IF( Found ) THEN
9469
IF(PRESENT(ValueLst)) ValueLst => Model % BodyForces(bf) % Values
9470
EXIT
9471
END IF
9472
END DO
9473
!------------------------------------------------------------------------------
9474
END FUNCTION ListCheckPresentAnyBodyForce
9475
!------------------------------------------------------------------------------
9476
9477
!------------------------------------------------------------------------------
9478
!> Check if the keyword is True in any body force.
9479
!------------------------------------------------------------------------------
9480
FUNCTION ListGetLogicalAnyBodyForce( Model, Name ) RESULT(Found)
9481
!------------------------------------------------------------------------------
9482
TYPE(Model_t) :: Model
9483
CHARACTER(LEN=*) :: Name
9484
LOGICAL :: Found, GotIt
9485
INTEGER :: bf
9486
9487
Found = .FALSE.
9488
DO bf = 1,Model % NumberOfBodyForces
9489
Found = ListGetLogical( Model % BodyForces(bf) % Values, Name, GotIt )
9490
IF( Found ) EXIT
9491
END DO
9492
!------------------------------------------------------------------------------
9493
END FUNCTION ListGetLogicalAnyBodyForce
9494
!------------------------------------------------------------------------------
9495
9496
!------------------------------------------------------------------------------
9497
!> Check if the keyword is present in any material.
9498
!------------------------------------------------------------------------------
9499
FUNCTION ListCheckPresentAnyMaterial( Model, Name, ValueLst ) RESULT(Found)
9500
!------------------------------------------------------------------------------
9501
TYPE(Model_t) :: Model
9502
CHARACTER(LEN=*) :: Name
9503
TYPE(ValueList_t), POINTER, OPTIONAL :: ValueLst
9504
LOGICAL :: Found
9505
INTEGER :: mat
9506
9507
Found = .FALSE.
9508
IF(PRESENT(ValueLst)) ValueLst => NULL()
9509
DO mat = 1,Model % NumberOfMaterials
9510
Found = ListCheckPresent( Model % Materials(mat) % Values, Name )
9511
IF( Found ) THEN
9512
IF(PRESENT(ValueLst)) ValueLst => Model % Materials(mat) % Values
9513
EXIT
9514
END IF
9515
END DO
9516
!------------------------------------------------------------------------------
9517
END FUNCTION ListCheckPresentAnyMaterial
9518
!------------------------------------------------------------------------------
9519
9520
9521
!------------------------------------------------------------------------------
9522
!> Check if the keyword is present in any solver.
9523
!------------------------------------------------------------------------------
9524
FUNCTION ListCheckPresentAnySolver( Model, Name, ValueLst ) RESULT(Found)
9525
!------------------------------------------------------------------------------
9526
TYPE(Model_t) :: Model
9527
CHARACTER(LEN=*) :: Name
9528
TYPE(ValueList_t), POINTER, OPTIONAL :: ValueLst
9529
LOGICAL :: Found
9530
INTEGER :: ind
9531
9532
Found = .FALSE.
9533
IF(PRESENT(ValueLst)) ValueLst => NULL()
9534
DO ind = 1,Model % NumberOfSolvers
9535
Found = ListCheckPresent( Model % Solvers(ind) % Values, Name )
9536
IF( Found ) THEN
9537
IF(PRESENT(ValueLst)) ValueLst => Model % Solvers(ind) % Values
9538
EXIT
9539
END IF
9540
END DO
9541
!------------------------------------------------------------------------------
9542
END FUNCTION ListCheckPresentAnySolver
9543
!------------------------------------------------------------------------------
9544
9545
9546
9547
!------------------------------------------------------------------------------
9548
!> Check if the keyword is present in any component.
9549
!------------------------------------------------------------------------------
9550
FUNCTION ListCheckPresentAnyComponent( Model, Name, ValueLst ) RESULT( Found )
9551
!------------------------------------------------------------------------------
9552
IMPLICIT NONE
9553
TYPE(Model_t) :: Model
9554
CHARACTER(LEN=*) :: Name
9555
TYPE(ValueList_t), POINTER, OPTIONAL :: ValueLst
9556
LOGICAL :: Found
9557
INTEGER :: ind
9558
9559
Found = .FALSE.
9560
IF(PRESENT(ValueLst)) ValueLst => NULL()
9561
DO ind=1, Model % NumberOfComponents
9562
Found = ListCheckPresent( Model % Components(ind) % Values, Name )
9563
IF( Found ) THEN
9564
IF(PRESENT(ValueLst)) ValueLst => Model % Components(ind) % Values
9565
EXIT
9566
END IF
9567
END DO
9568
!------------------------------------------------------------------------------
9569
END FUNCTION ListCheckPresentAnyComponent
9570
!------------------------------------------------------------------------------
9571
9572
9573
!------------------------------------------------------------------------------
9574
FUNCTION ListCheckPrefixAnyComponent( Model, Name ) RESULT( Found )
9575
!------------------------------------------------------------------------------
9576
IMPLICIT NONE
9577
TYPE(Model_t) :: Model
9578
CHARACTER(LEN=*) :: Name
9579
LOGICAL :: Found
9580
INTEGER :: ind
9581
TYPE(ValueListEntry_t), POINTER :: ptr
9582
9583
Found = .FALSE.
9584
DO ind=1, Model % NumberOfComponents
9585
ptr => ListFindPrefix( Model % Components(ind) % Values, Name, Found )
9586
IF( Found ) EXIT
9587
END DO
9588
!------------------------------------------------------------------------------
9589
END FUNCTION ListCheckPrefixAnyComponent
9590
!------------------------------------------------------------------------------
9591
9592
9593
9594
!------------------------------------------------------------------------------
9595
!> Check if the keyword is true in any component.
9596
!------------------------------------------------------------------------------
9597
FUNCTION ListGetLogicalAnyComponent( Model, Name ) RESULT( Found )
9598
!------------------------------------------------------------------------------
9599
IMPLICIT NONE
9600
9601
TYPE(Model_t) :: Model
9602
CHARACTER(LEN=*) :: Name
9603
LOGICAL :: Found, GotIt
9604
INTEGER :: ind
9605
9606
Found = .FALSE.
9607
DO ind=1, Model % NumberOfComponents
9608
Found = ListGetLogical( Model % Components(ind) % Values, Name, GotIt )
9609
IF( Found ) EXIT
9610
END DO
9611
!------------------------------------------------------------------------------
9612
END FUNCTION ListGetLogicalAnyComponent
9613
!------------------------------------------------------------------------------
9614
9615
!------------------------------------------------------------------------------
9616
!> Check if the keyword in any material is defined as an array
9617
!------------------------------------------------------------------------------
9618
FUNCTION ListCheckAnyMaterialIsArray( Model, Name ) RESULT(IsArray)
9619
!------------------------------------------------------------------------------
9620
TYPE(Model_t) :: Model
9621
CHARACTER(LEN=*) :: Name
9622
LOGICAL :: IsArray
9623
LOGICAL :: Found
9624
INTEGER :: mat, n, m
9625
TYPE(ValueListEntry_t), POINTER :: ptr
9626
9627
IsArray = .FALSE.
9628
DO mat = 1,Model % NumberOfMaterials
9629
ptr => ListFind(Model % Materials(mat) % Values,Name,Found)
9630
IF( .NOT. ASSOCIATED( ptr ) ) CYCLE
9631
IF ( .NOT. ASSOCIATED(ptr % FValues) ) THEN
9632
CALL Fatal( 'ListCheckAnyMaterialArray', 'Value type for property ['//TRIM(Name)// &
9633
'] not used consistently.')
9634
END IF
9635
n = SIZE( ptr % FValues,1 )
9636
m = SIZE( ptr % FValues,2 )
9637
IsArray = ( n > 1 ) .OR. ( m > 1 )
9638
IF( IsArray ) EXIT
9639
END DO
9640
!------------------------------------------------------------------------------
9641
END FUNCTION ListCheckAnyMaterialIsArray
9642
!------------------------------------------------------------------------------
9643
9644
9645
!------------------------------------------------------------------------------
9646
!> Check if the keyword is True in any material.
9647
!------------------------------------------------------------------------------
9648
FUNCTION ListGetLogicalAnyMaterial( Model, Name ) RESULT(Found)
9649
!------------------------------------------------------------------------------
9650
TYPE(Model_t) :: Model
9651
CHARACTER(LEN=*) :: Name
9652
LOGICAL :: Found, GotIt
9653
INTEGER :: mat
9654
9655
Found = .FALSE.
9656
DO mat = 1,Model % NumberOfMaterials
9657
Found = ListGetLogical( Model % Materials(mat) % Values, Name, GotIt )
9658
IF( Found ) EXIT
9659
END DO
9660
!------------------------------------------------------------------------------
9661
END FUNCTION ListGetLogicalAnyMaterial
9662
!------------------------------------------------------------------------------
9663
9664
9665
!------------------------------------------------------------------------------
9666
!> Check if the keyword is True in any solver.
9667
!------------------------------------------------------------------------------
9668
FUNCTION ListGetLogicalAnySolver( Model, Name ) RESULT(Found)
9669
!------------------------------------------------------------------------------
9670
TYPE(Model_t) :: Model
9671
CHARACTER(LEN=*) :: Name
9672
LOGICAL :: Found, GotIt
9673
INTEGER :: ind
9674
9675
Found = .FALSE.
9676
DO ind = 1,Model % NumberOfSolvers
9677
Found = ListGetLogical( Model % Solvers(ind) % Values, Name, GotIt )
9678
IF( Found ) EXIT
9679
END DO
9680
!------------------------------------------------------------------------------
9681
END FUNCTION ListGetLogicalAnySolver
9682
!------------------------------------------------------------------------------
9683
9684
9685
!------------------------------------------------------------------------------
9686
!> Check if the keyword is present in any equation.
9687
!------------------------------------------------------------------------------
9688
FUNCTION ListCheckPresentAnyEquation( Model, Name, ValueLst ) RESULT(Found)
9689
!------------------------------------------------------------------------------
9690
TYPE(Model_t) :: Model
9691
CHARACTER(LEN=*) :: Name
9692
TYPE(ValueList_t), POINTER, OPTIONAL :: ValueLst
9693
LOGICAL :: Found
9694
INTEGER :: eq
9695
9696
Found = .FALSE.
9697
IF(PRESENT(ValueLst)) ValueLst => NULL()
9698
DO eq = 1,Model % NumberOfEquations
9699
Found = ListCheckPresent( Model % Equations(eq) % Values, Name )
9700
IF( Found ) THEN
9701
IF(PRESENT(ValueLst)) ValueLst => Model % Equations(eq) % Values
9702
EXIT
9703
END IF
9704
END DO
9705
!------------------------------------------------------------------------------
9706
END FUNCTION ListCheckPresentAnyEquation
9707
!------------------------------------------------------------------------------
9708
9709
!------------------------------------------------------------------------------
9710
!> Check if the keyword is True in any equation.
9711
!------------------------------------------------------------------------------
9712
FUNCTION ListGetLogicalAnyEquation( Model, Name ) RESULT(Found)
9713
!------------------------------------------------------------------------------
9714
TYPE(Model_t) :: Model
9715
CHARACTER(LEN=*) :: Name
9716
LOGICAL :: Found, GotIt
9717
INTEGER :: eq
9718
9719
Found = .FALSE.
9720
DO eq = 1,Model % NumberOfEquations
9721
Found = ListGetLogical( Model % Equations(eq) % Values, Name, GotIt )
9722
IF( Found ) EXIT
9723
END DO
9724
!------------------------------------------------------------------------------
9725
END FUNCTION ListGetLogicalAnyEquation
9726
!------------------------------------------------------------------------------
9727
9728
9729
!------------------------------------------------------------------------------
9730
!> Elmer may include scalar and vector variables which may be known by their
9731
!> original name or have an alias. For historical reasons they are introduced
9732
!> by two quite separate ways. This subroutine tries to make the definition of
9733
!> variables for saving more straight-forward.
9734
!------------------------------------------------------------------------------
9735
SUBROUTINE CreateListForSaving( Model, List, ShowVariables, ClearList, &
9736
UseGenericKeyword )
9737
!------------------------------------------------------------------------------
9738
IMPLICIT NONE
9739
!------------------------------------------------------------------------------
9740
TYPE(Model_t) :: Model
9741
TYPE(ValueList_t), POINTER :: List
9742
LOGICAL :: ShowVariables
9743
LOGICAL, OPTIONAL :: ClearList
9744
LOGICAL, OPTIONAL :: UseGenericKeyword
9745
!------------------------------------------------------------------------------
9746
INTEGER :: i,j,k,l,LoopDim, VarDim,FullDim,DOFs,dim,Comp
9747
TYPE(Variable_t), POINTER :: Variables, Var, Var1
9748
CHARACTER(LEN=2*MAX_NAME_LEN) :: VarName, VarStr, str
9749
LOGICAL :: IsVector, Set, GotIt, ComponentVector, ThisOnly, IsIndex, &
9750
EnforceVectors, UseGeneric, DisplacementV
9751
INTEGER :: Nvector, Nscalar
9752
TYPE(ValueList_t), POINTER :: Params
9753
9754
Params => Model % Solver % Values
9755
Variables => Model % Mesh % Variables
9756
9757
IF( .NOT. ASSOCIATED( Variables ) ) THEN
9758
CALL Warn('CreateListForSaving','Mesh does not include any variables!')
9759
RETURN
9760
END IF
9761
9762
UseGeneric = .FALSE.
9763
IF( PRESENT( UseGenericKeyword ) ) THEN
9764
UseGeneric = UseGenericKeyword
9765
END IF
9766
9767
9768
!------------------------------------------------------------------------------
9769
! Sometimes the list must be cleared in order to use it for a different mesh
9770
!-----------------------------------------------------------------------------
9771
IF( PRESENT( ClearList ) ) THEN
9772
IF( ClearList ) THEN
9773
IF( UseGeneric ) THEN
9774
DO i=1,999
9775
WRITE(VarStr,'(A,I0)') 'Variable ',i
9776
IF( ListCheckPresent( List, VarStr ) ) THEN
9777
CALL ListRemove( List, VarStr )
9778
ELSE
9779
EXIT
9780
END IF
9781
END DO
9782
ELSE
9783
DO i=1,999
9784
WRITE(VarStr,'(A,I0)') 'Scalar Field ',i
9785
IF( ListCheckPresent( List, VarStr ) ) THEN
9786
CALL ListRemove( List, VarStr )
9787
ELSE
9788
EXIT
9789
END IF
9790
END DO
9791
9792
DO i=1,999
9793
WRITE(VarStr,'(A,I0)') 'Vector Field ',i
9794
IF( ListCheckPresent( List, VarStr ) ) THEN
9795
CALL ListRemove( List, VarStr )
9796
ELSE
9797
EXIT
9798
END IF
9799
9800
WRITE(VarStr,'(A,I0,A)') 'Vector Field ',i,' Complement'
9801
IF( ListCheckPresent( List, VarStr ) ) THEN
9802
CALL ListRemove( List, VarStr )
9803
END IF
9804
END DO
9805
9806
END IF
9807
END IF
9808
END IF
9809
9810
!-------------------------------------------------------------------
9811
! First check that there is a need to create the list i.e. it is not
9812
! already manually defined
9813
!-------------------------------------------------------------------
9814
IF( UseGeneric ) THEN
9815
IF( ListCheckPresent( List,'Variable 1' ) ) THEN
9816
CALL Info('CreateListForSaving','Variable 1 exists, creating no list!',Level=10)
9817
RETURN
9818
END IF
9819
ELSE
9820
IF( ListCheckPresent( List,'Scalar Field 1' ) ) THEN
9821
CALL Info('CreateListForSaving','Scalar Field 1 exists, creating no list!',Level=10)
9822
RETURN
9823
END IF
9824
9825
IF( ListCheckPresent( List,'Vector Field 1' ) ) THEN
9826
CALL Info('CreateListForSaving','Vector Field 1 exists, creating no list!',Level=10)
9827
RETURN
9828
END IF
9829
END IF
9830
9831
Nscalar = 0
9832
Nvector = 0
9833
9834
9835
ThisOnly = .NOT. ListGetLogical( Params,'Interpolate Fields',GotIt)
9836
dim = Model % Mesh % MeshDim
9837
9838
EnforceVectors = ListGetLogical( Params,'Enforce Vectors',GotIt)
9839
IF(.NOT. GotIt ) EnforceVectors = .TRUE.
9840
9841
9842
! For historical reasons treat "displacement" in a special way
9843
! but only if it exists as vector. Otherwise it will be treated by its components.
9844
! This fixes output for the elasticity solver in case of mixed solution.
9845
Var => Variables
9846
DisplacementV = .FALSE.
9847
DO WHILE( ASSOCIATED( Var ) )
9848
IF( Var % Name == 'displacement' ) DisplacementV = .TRUE.
9849
Var => Var % Next
9850
END DO
9851
9852
9853
Var => Variables
9854
9855
DO WHILE( ASSOCIATED( Var ) )
9856
9857
! Skip if variable is not active for saving
9858
IF ( .NOT. Var % Output ) THEN
9859
Var => Var % Next
9860
CYCLE
9861
END IF
9862
9863
! Skip if variable is global one
9864
IF ( SIZE( Var % Values ) == Var % DOFs ) THEN
9865
Var => Var % Next
9866
CYCLE
9867
END IF
9868
9869
IF( Var % TYPE == Variable_global ) THEN
9870
Var => Var % Next
9871
CYCLE
9872
ELSE IF( Var % TYPE == Variable_on_gauss_points ) THEN
9873
CONTINUE
9874
9875
ELSE IF( Var % TYPE == Variable_on_elements ) THEN
9876
CONTINUE
9877
9878
END IF
9879
9880
! Skip if variable is otherwise strange in size
9881
IF(.NOT. ASSOCIATED( Var % Perm ) ) THEN
9882
IF( Var % TYPE == Variable_on_nodes ) THEN
9883
IF( SIZE( Var % Values ) /= Var % Dofs * Model % Mesh % NumberOfNodes ) THEN
9884
Var => Var % Next
9885
CYCLE
9886
END IF
9887
ELSE IF( Var % TYPE == Variable_on_nodes_on_elements ) THEN
9888
IF( SIZE( Var % Values ) /= Var % Dofs * Model % Mesh % NumberOfBulkElements ) THEN
9889
Var => Var % Next
9890
CYCLE
9891
END IF
9892
END IF
9893
END IF
9894
9895
VarDim = Var % Dofs
9896
IsVector = (VarDim > 1)
9897
Set = .FALSE.
9898
9899
WRITE(VarName,'(A)') TRIM(Var % Name)
9900
9901
SELECT CASE(Var % Name)
9902
9903
CASE( 'coordinate 1','coordinate 2','coordinate 3' )
9904
! These are treated separatetely as coordinates are not typically saved
9905
9906
9907
CASE( 'mesh update' )
9908
! Mesh update is treated separately because its special connection to displacement
9909
Set = .TRUE.
9910
IF(.NOT. UseGeneric ) THEN
9911
Var1 => Variables
9912
DO WHILE( ASSOCIATED( Var1 ) )
9913
IF ( TRIM(Var1 % Name) == 'displacement' ) EXIT
9914
Var1 => Var1 % Next
9915
END DO
9916
IF ( ASSOCIATED( Var1 ) ) Set = .FALSE.
9917
END IF
9918
9919
CASE('mesh update 1','mesh update 2', 'mesh update 3' )
9920
9921
CASE( 'displacement' )
9922
Set = .TRUE.
9923
! mesh update is by default the complement to displacement
9924
! However, for generic variablelist the complement is not active
9925
IF(.NOT. UseGeneric ) THEN
9926
Var1 => Variables
9927
DO WHILE( ASSOCIATED( Var1 ) )
9928
IF ( TRIM(Var1 % Name) == 'mesh update' ) EXIT
9929
Var1 => Var1 % Next
9930
END DO
9931
IF ( ASSOCIATED( Var1 ) ) THEN
9932
WRITE(VarStr,'(A,I0,A)') 'Vector Field ',Nvector+1,' Complement'
9933
CALL ListAddString( List ,TRIM(VarStr),'mesh update')
9934
END IF
9935
END IF
9936
9937
!CASE( 'displacement 1','displacement 2','displacement 3')
9938
9939
9940
CASE DEFAULT
9941
! All vector variables are assumed to be saved using its components
9942
! rather than vector itself.
9943
IF ( VarDim == 1 ) THEN
9944
Set = .TRUE.
9945
9946
str = ' '
9947
j = LEN_TRIM(Var % Name)
9948
DO i=1,j
9949
str(i:i) = Var % Name(i:i)
9950
END DO
9951
9952
IsIndex = .FALSE.
9953
Comp = 0
9954
k = INDEX( str(:j),' ',BACK=.TRUE.)
9955
9956
IF( k > 0 ) THEN
9957
IsIndex = ( VERIFY( str(k:j),' 0123456789') == 0 )
9958
IF( IsIndex ) READ( str(k:j), * ) Comp
9959
END IF
9960
9961
! This is the easy way of checking that the component belongs to a vector
9962
! The size of the vector can be either dim or 3.
9963
GotIt = .FALSE.
9964
IF( IsIndex ) THEN
9965
Var1 => VariableGet(Variables,TRIM(str(1:k)),ThisOnly)
9966
IF( ASSOCIATED( Var1 ) ) THEN
9967
GotIt = .TRUE.
9968
IsVector = ( Var1 % Dofs == Dim .OR. Var1 % Dofs == 3 )
9969
Set = ( Comp == 1 .OR. .NOT. IsVector )
9970
END IF
9971
END IF
9972
9973
! This is a hard way of ensuring that the component belongs to a vector
9974
! Check that there are exactly dim number of components
9975
! If so save the quantity as a vector, otherwise componentwise
9976
IF( EnforceVectors .AND. .NOT. GotIt ) THEN
9977
IF( Comp == 1 ) THEN
9978
! If we have the 1st component we need at least dim (2 or 3) components
9979
! to have a vector.
9980
Var1 => VariableGet(Variables,TRIM(str(1:j-2))//' '//I2S(dim),ThisOnly)
9981
9982
! However, if the 4th component also exists then this cannot be a vector
9983
IF( ASSOCIATED(Var1)) THEN
9984
Var1 => VariableGet(Variables,TRIM(str(1:j-2))//' '//I2S(4),ThisOnly)
9985
IsVector = .NOT. ASSOCIATED(Var1)
9986
END IF
9987
9988
ELSE IF( Comp == 2 .OR. Comp == 3 ) THEN
9989
! Associated to the previous case, cycle the other components of the vector
9990
! and cycle them if they are part of the vector that will be detected above.
9991
9992
! 2D: 2 or 3 components
9993
! 3D: 3 components
9994
Var1 => VariableGet(Variables,TRIM(str(1:j-2))//' 1',ThisOnly)
9995
IF( ASSOCIATED( Var1 ) ) THEN
9996
Var1 => VariableGet(Variables,TRIM(str(1:j-2))//' '//I2S(4),ThisOnly)
9997
Set = ASSOCIATED( Var1 )
9998
IF( .NOT. Set ) THEN
9999
IF( Comp == 2 .AND. dim == 3 ) THEN
10000
Var1 => VariableGet(Variables,TRIM(str(1:j-2))//' '//I2S(dim),ThisOnly)
10001
Set = .NOT. ASSOCIATED( Var1 )
10002
END IF
10003
END IF
10004
END IF
10005
END IF
10006
END IF
10007
10008
! Remove the trailing numbers as they are not needed in this case.
10009
IF( Set ) THEN
10010
IF(IsVector) WRITE(VarName,'(A)') TRIM(str(1:j-2))
10011
10012
! This is a special case as historically this is saved as vector
10013
IF(VarName == 'displacement' .AND. DisplacementV ) Set = .FALSE.
10014
END IF
10015
END IF
10016
END SELECT
10017
10018
10019
10020
!---------------------------------------------------------------------------
10021
! Set the default variable names that have not been set
10022
!------------------------------------------------------------------------
10023
IF( Set ) THEN
10024
IF( UseGeneric ) THEN
10025
Nscalar = Nscalar + 1
10026
WRITE(VarStr,'(A,I0)') 'Variable ',Nscalar
10027
ELSE IF( IsVector ) THEN
10028
Nvector = Nvector + 1
10029
WRITE(VarStr,'(A,I0)') 'Vector Field ',Nvector
10030
ELSE
10031
Nscalar = Nscalar + 1
10032
WRITE(VarStr,'(A,I0)') 'Scalar Field ',Nscalar
10033
END IF
10034
CALL ListAddString( List,TRIM(VarStr),TRIM(VarName) )
10035
END IF
10036
10037
Var => Var % Next
10038
END DO
10039
10040
10041
IF( ShowVariables ) THEN
10042
CALL Info('CreateListForSaving','Field Variables for Saving')
10043
IF( UseGeneric ) THEN
10044
DO i=1,Nscalar
10045
WRITE(VarStr,'(A,I0)') 'Variable ',i
10046
VarName = ListGetString( List, VarStr,GotIt )
10047
IF( GotIt ) THEN
10048
WRITE( Message,'(A)') TRIM(VarStr)//': '//TRIM(VarName)
10049
CALL Info('CreateListForSaving',Message,Level=6)
10050
END IF
10051
END DO
10052
ELSE
10053
DO i=1,Nscalar
10054
WRITE(VarStr,'(A,I0)') 'Scalar Field ',i
10055
VarName = ListGetString( List, VarStr,GotIt )
10056
IF( GotIt ) THEN
10057
WRITE( Message,'(A)') TRIM(VarStr)//': '//TRIM(VarName)
10058
CALL Info('CreateListForSaving',Message,Level=6)
10059
END IF
10060
END DO
10061
10062
DO i=1,Nvector
10063
WRITE(VarStr,'(A,I0)') 'Vector Field ',i
10064
VarName = ListGetString( List, VarStr,GotIt )
10065
IF( GotIt ) THEN
10066
WRITE( Message,'(A)') TRIM(VarStr)//': '//TRIM(VarName)
10067
CALL Info('CreateListForSaving',Message,Level=6)
10068
END IF
10069
END DO
10070
10071
DO i=1,Nvector
10072
WRITE(VarStr,'(A,I0,A)') 'Vector Field ',i,' Complement'
10073
VarName = ListGetString( List, VarStr, GotIt )
10074
IF( GotIt ) THEN
10075
WRITE( Message,'(A)') TRIM(VarStr)//': '//TRIM(VarName)
10076
CALL Info('CreateListForSaving',Message,Level=6)
10077
END IF
10078
END DO
10079
END IF
10080
END IF
10081
10082
END SUBROUTINE CreateListForSaving
10083
10084
10085
10086
!------------------------------------------------------------------------------
10087
!> A timer that uses a list structure to store the times making in
10088
!> generally applicable without any upper limit on the number of timers.
10089
!> This resets the timer.
10090
!-----------------------------------------------------------------------------
10091
10092
SUBROUTINE ResetTimer(TimerName)
10093
CHARACTER(*) :: TimerName
10094
REAL(KIND=dp) :: ct, rt
10095
LOGICAL :: Found,FirstTime=.TRUE.
10096
10097
IF( FirstTime ) THEN
10098
FirstTime=.FALSE.
10099
TimerPassive = ListGetLogical( CurrentModel % Simulation,'Timer Passive',Found)
10100
TimerCumulative = ListGetLogical( CurrentModel % Simulation,'Timer Cumulative',Found)
10101
TimerRealTime = ListGetLogical( CurrentModel % Simulation,'Timer Real Time',Found)
10102
TimerCPUTime = ListGetLogical( CurrentModel % Simulation,'Timer CPU Time',Found)
10103
IF( .NOT. (TimerRealTime .OR. TimerCPUTime ) ) TimerRealTime = .TRUE.
10104
TimerPrefix = ListGetString( CurrentModel % Simulation,'Timer Prefix',Found )
10105
IF( .NOT. Found ) THEN
10106
IF( ListGetLogical( CurrentModel % Simulation,'Timer Results',Found ) ) THEN
10107
TimerPrefix = 'res:'
10108
ELSE
10109
TimerPrefix = 'timer:'
10110
END IF
10111
END IF
10112
END IF
10113
10114
10115
IF( TimerPassive ) RETURN
10116
10117
IF( TimerCPUTime ) THEN
10118
ct = CPUTime()
10119
CALL ListAddConstReal( TimerList,TRIM(TimerName)//' cpu time',ct )
10120
END IF
10121
10122
IF( TimerRealTime ) THEN
10123
rt = RealTime()
10124
CALL ListAddConstReal( TimerList,TRIM(TimerName)//' real time',rt )
10125
END IF
10126
10127
IF( TimerCumulative ) THEN
10128
IF( TimerCPUTime ) THEN
10129
IF( .NOT. ListCheckPresent( CurrentModel % Simulation,TRIM(TimerPrefix)//' '//TRIM(TimerName)//' cpu time') ) THEN
10130
CALL ListAddConstReal( CurrentModel % Simulation,TRIM(TimerPrefix)//' '//TRIM(TimerName)//' cpu time',0.0_dp )
10131
END IF
10132
END IF
10133
IF( TimerRealTime ) THEN
10134
IF( .NOT. ListCheckPresent( CurrentModel % Simulation,TRIM(TimerPrefix)//' '//TRIM(TimerName)//' real time') ) THEN
10135
CALL ListAddConstReal( CurrentModel % Simulation,TRIM(TimerPrefix)//' '//TRIM(TimerName)//' real time',0.0_dp )
10136
END IF
10137
END IF
10138
END IF
10139
10140
END SUBROUTINE ResetTimer
10141
10142
10143
!-----------------------------------------------------------------------------
10144
!> Delete an existing timer.
10145
!----------------------------------------------------------------------------
10146
SUBROUTINE DeleteTimer(TimerName)
10147
CHARACTER(*) :: TimerName
10148
10149
IF( TimerPassive ) RETURN
10150
10151
IF( TimerCPUTime ) THEN
10152
CALL ListRemove( TimerList, TRIM(TimerName)//' cpu time' )
10153
END IF
10154
10155
IF( TimerRealTime ) THEN
10156
CALL ListRemove( TimerList, TRIM(TimerName)//' real time' )
10157
END IF
10158
10159
END SUBROUTINE DeleteTimer
10160
10161
!-----------------------------------------------------------------------------
10162
!> Check current time of the timer.
10163
!----------------------------------------------------------------------------
10164
SUBROUTINE CheckTimer(TimerName, Level, Delete, Reset)
10165
CHARACTER(*) :: TimerName
10166
INTEGER, OPTIONAL :: Level
10167
LOGICAL, OPTIONAL :: Reset, Delete
10168
10169
REAL(KIND=dp) :: ct0,rt0,ct, rt, cumct, cumrt
10170
LOGICAL :: Found
10171
10172
IF( TimerPassive ) RETURN
10173
10174
IF( TimerCPUTime ) THEN
10175
ct0 = ListGetConstReal( TimerList,TRIM(TimerName)//' cpu time',Found)
10176
IF( Found ) THEN
10177
ct = CPUTime() - ct0
10178
WRITE(Message,'(a,f10.4,a)') 'Elapsed CPU time: ',ct,' (s)'
10179
CALL Info(TRIM(TimerName),Message,Level=Level)
10180
END IF
10181
END IF
10182
10183
IF( TimerRealTime ) THEN
10184
rt0 = ListGetConstReal( TimerList,TRIM(TimerName)//' real time',Found)
10185
IF( Found ) THEN
10186
rt = RealTime() - rt0
10187
WRITE(Message,'(a,f10.4,a)') 'Elapsed REAL time: ',rt,' (s)'
10188
CALL Info(TRIM(TimerName),Message,Level=Level)
10189
END IF
10190
END IF
10191
10192
10193
IF( TimerCPUTime ) THEN
10194
IF( TimerCumulative ) THEN
10195
cumct = ListGetConstReal(CurrentModel % Simulation,&
10196
TRIM(TimerPrefix)//' '//TRIM(TimerName)//' cpu time',Found)
10197
IF( Found ) THEN
10198
ct = ct + cumct
10199
WRITE(Message,'(a,f10.4,a)') 'Elapsed CPU time cumulative: ',ct,' (s)'
10200
CALL Info(TRIM(TimerName),Message,Level=Level)
10201
ELSE
10202
CALL Warn('CheckTimer',&
10203
'Requesting previous CPU time from non-existing timer: '//TRIM(TimerName) )
10204
END IF
10205
END IF
10206
CALL ListAddConstReal(CurrentModel % Simulation,&
10207
TRIM(TimerPrefix)//' '//TRIM(TimerName)//' cpu time',ct)
10208
10209
END IF
10210
IF( TimerRealTime ) THEN
10211
IF( TimerCumulative ) THEN
10212
cumrt = ListGetConstReal(CurrentModel % Simulation,&
10213
TRIM(TimerPrefix)//' '//TRIM(TimerName)//' real time',Found)
10214
IF( Found ) THEN
10215
rt = rt + cumrt
10216
WRITE(Message,'(a,f10.4,a)') 'Elapsed real time cumulative: ',rt,' (s)'
10217
CALL Info(TRIM(TimerName),Message,Level=Level)
10218
ELSE
10219
CALL Warn('CheckTimer',&
10220
'Requesting previous real time from non-existing timer: '//TRIM(TimerName) )
10221
END IF
10222
END IF
10223
CALL ListAddConstReal(CurrentModel % Simulation,&
10224
TRIM(TimerPrefix)//' '//TRIM(TimerName)//' real time',rt)
10225
END IF
10226
10227
10228
IF( PRESENT( Reset ) ) THEN
10229
IF( Reset ) THEN
10230
IF( TimerCPUTime ) THEN
10231
CALL ListAddConstReal( TimerList,TRIM(TimerName)//' cpu time',ct )
10232
END IF
10233
IF( TimerRealTime ) THEN
10234
CALL ListAddConstReal( TimerList,TRIM(TimerName)//' real time',rt )
10235
END IF
10236
END IF
10237
END IF
10238
10239
IF( PRESENT( Delete ) ) THEN
10240
IF( Delete ) CALL DeleteTimer( TimerName )
10241
END IF
10242
10243
END SUBROUTINE CheckTimer
10244
10245
10246
!> Returns the angular frequency
10247
FUNCTION ListGetAngularFrequency(ValueList,Found,UElement) RESULT(w)
10248
REAL(KIND=dp) :: w
10249
TYPE(ValueList_t), OPTIONAL, POINTER :: ValueList
10250
LOGICAL, OPTIONAL :: Found
10251
LOGICAL :: GotIt
10252
TYPE(Element_t), TARGET :: UElement
10253
TYPE(Element_t), POINTER :: Element
10254
OPTIONAL :: UElement
10255
INTEGER :: elem_id,eq_id,mat_id
10256
10257
! This is rather complicated since it should replace all the various strategies
10258
! that have been used in different solvers.
10259
!------------------------------------------------------------------------------
10260
10261
! The only way frequency may depend on element is that it sits in equation block
10262
!--------------------------------------------------------------------------------
10263
IF( PRESENT( ValueList ) ) THEN
10264
w = 2 * PI * ListGetCReal( ValueList,'Frequency',GotIt)
10265
IF(.NOT. GotIt) w = ListGetCReal( ValueList,'Angular Frequency',GotIt)
10266
ELSE
10267
GotIt = .FALSE.
10268
END IF
10269
10270
! It seems that the equation section is used to allow compliance with ElmerGUI
10271
!------------------------------------------------------------------------------
10272
IF( .NOT. GotIt ) THEN
10273
IF(PRESENT(UElement)) THEN
10274
Element => UElement
10275
eq_id = ListGetInteger( CurrentModel % Bodies(Element % bodyid) % Values,'Equation')
10276
w = 2 * PI * ListGetCReal( &
10277
CurrentModel % Equations(eq_id) % Values,'Frequency',GotIt)
10278
IF(.NOT. GotIt) w = ListGetCReal( &
10279
CurrentModel % Equations(eq_id) % Values,'Angular Frequency',GotIt)
10280
END IF
10281
END IF
10282
10283
! Check also the material section of the given element...
10284
!------------------------------------------------------------------------------
10285
IF( .NOT. GotIt ) THEN
10286
IF(PRESENT(UElement)) THEN
10287
Element => UElement
10288
mat_id = ListGetInteger( CurrentModel % Bodies(Element % bodyid) % Values,'Material',GotIt)
10289
IF( GotIt ) THEN
10290
w = 2 * PI * ListGetCReal( &
10291
CurrentModel % Materials(mat_id) % Values,'Frequency',GotIt)
10292
IF(.NOT. GotIt) w = ListGetCReal( &
10293
CurrentModel % Materials(mat_id) % Values,'Angular Frequency',GotIt)
10294
END IF
10295
END IF
10296
END IF
10297
10298
! Normally the constant frequency is given in Simulation (or solver) block
10299
!-------------------------------------------------------------------------
10300
IF(.NOT. GotIt) w = 2 * PI * ListGetCReal( &
10301
CurrentModel % Simulation,'Frequency',GotIt)
10302
IF(.NOT. GotIt ) w = ListGetCReal( &
10303
CurrentModel % Simulation,'Angular Frequency',GotIt)
10304
10305
IF(.NOT. GotIt ) w = 2 * PI * ListGetCReal( &
10306
CurrentModel % Solver % Values,'Frequency',GotIt)
10307
IF(.NOT. GotIt ) w = ListGetCReal( &
10308
CurrentModel % Solver % Values,'Angular Frequency',GotIt)
10309
10310
! It seems that the equation section is used to allow compliance with ElmerGUI
10311
! If element given, don't do this as it has been done before already.
10312
!------------------------------------------------------------------------------
10313
IF( .NOT. GotIt ) THEN
10314
IF(.NOT. PRESENT(UElement)) THEN
10315
elem_id = CurrentModel % Solver % ActiveElements(1)
10316
Element => CurrentModel % Elements(elem_id)
10317
eq_id = ListGetInteger( CurrentModel % Bodies(Element % bodyid) % Values,'Equation')
10318
w = 2 * PI * ListGetCReal( &
10319
CurrentModel % Equations(eq_id) % Values,'Frequency',GotIt)
10320
IF(.NOT. GotIt) w = ListGetCReal( &
10321
CurrentModel % Equations(eq_id) % Values,'Angular Frequency',GotIt)
10322
END IF
10323
END IF
10324
10325
! Check also the material section of the 1st element, if not element given.
10326
!------------------------------------------------------------------------------
10327
IF( .NOT. GotIt ) THEN
10328
IF(.NOT. PRESENT(UElement)) THEN
10329
elem_id = CurrentModel % Solver % ActiveElements(1)
10330
Element => CurrentModel % Elements(elem_id)
10331
mat_id = ListGetInteger( CurrentModel % Bodies(Element % bodyid) % Values,'Material',GotIt)
10332
IF(GotIt) THEN
10333
w = 2 * PI * ListGetCReal( &
10334
CurrentModel % Materials(mat_id) % Values,'Frequency',GotIt)
10335
IF(.NOT. GotIt) w = ListGetCReal( &
10336
CurrentModel % Materials(mat_id) % Values,'Angular Frequency',GotIt)
10337
END IF
10338
END IF
10339
END IF
10340
10341
IF( PRESENT( Found ) ) THEN
10342
Found = GotIt
10343
ELSE IF(.NOT. GotIt ) THEN
10344
CALL Warn('ListGetAngularFrequency','Angular frequency could not be determined!')
10345
END IF
10346
END FUNCTION ListGetAngularFrequency
10347
10348
10349
!------------------------------------------------------------------------------
10350
!> Returns handle to the Solver value list of the active solver
10351
FUNCTION ListGetSolverParams(Solver) RESULT(SolverParam)
10352
!------------------------------------------------------------------------------
10353
TYPE(ValueList_t), POINTER :: SolverParam
10354
TYPE(Solver_t), OPTIONAL :: Solver
10355
10356
IF ( PRESENT(Solver) ) THEN
10357
SolverParam => Solver % Values
10358
ELSE
10359
SolverParam => CurrentModel % Solver % Values
10360
END IF
10361
!------------------------------------------------------------------------------
10362
END FUNCTION ListGetSolverParams
10363
!------------------------------------------------------------------------------
10364
10365
!-------------------------------------------------------------------------------
10366
!> evaluates lua string to real array
10367
!-------------------------------------------------------------------------------
10368
SUBROUTINE ElmerEvalLuaT(L, ptr, T, F, varcount)
10369
!-------------------------------------------------------------------------------
10370
TYPE(LuaState_t) :: L
10371
TYPE(ValueListEntry_t), POINTER :: ptr
10372
REAL(KIND=C_DOUBLE), INTENT(IN) :: T(:)
10373
REAL(KIND=C_DOUBLE), INTENT(OUT) :: F(:,:)
10374
INTEGER :: VARCOUNT
10375
!-------------------------------------------------------------------------------
10376
integer :: lstat
10377
10378
#ifdef HAVE_LUA
10379
L % tx(1:varcount) = T(1:varcount) ! this should be superfluous
10380
call lua_exec_fun(L, ptr % cvalue, 0, size(F,1)*size(F,2))
10381
CALL lua_poptensor(L, F)
10382
#else
10383
CALL Fatal('ElmerEvalLuaT', 'Lua not compiled in.')
10384
#endif
10385
10386
!-------------------------------------------------------------------------------
10387
END SUBROUTINE ElmerEvalLuaT
10388
!-------------------------------------------------------------------------------
10389
10390
!-------------------------------------------------------------------------------
10391
!> evaluates lua string to real vector
10392
!-------------------------------------------------------------------------------
10393
SUBROUTINE ElmerEvalLuaV(L, ptr, T, F, varcount)
10394
!-------------------------------------------------------------------------------
10395
TYPE(LuaState_t) :: L
10396
TYPE(ValueListEntry_t), POINTER :: ptr
10397
REAL(KIND=C_DOUBLE), INTENT(IN) :: T(:)
10398
REAL(KIND=C_DOUBLE), INTENT(INOUT) :: F(:)
10399
INTEGER :: VARCOUNT
10400
!-------------------------------------------------------------------------------
10401
integer :: lstat
10402
10403
#ifdef HAVE_LUA
10404
L % tx(1:varcount) = T(1:varcount) ! this should be superfluous
10405
call lua_exec_fun(L, ptr % cvalue, 0, size(F,1))
10406
CALL lua_popvector(L, F)
10407
#else
10408
CALL Fatal('ElmerEvalLuaV', 'Lua not compiled in.')
10409
#endif
10410
10411
!-------------------------------------------------------------------------------
10412
END SUBROUTINE ElmerEvalLuaV
10413
!-------------------------------------------------------------------------------
10414
10415
!-------------------------------------------------------------------------------
10416
!> evaluates lua string to real scalar
10417
!-------------------------------------------------------------------------------
10418
SUBROUTINE ElmerEvalLuaS(L, ptr, T, F, varcount)
10419
!-------------------------------------------------------------------------------
10420
TYPE(LuaState_t) :: L
10421
TYPE(ValueListEntry_t), POINTER :: ptr
10422
REAL(KIND=C_DOUBLE), INTENT(IN) :: T(:)
10423
REAL(KIND=C_DOUBLE), INTENT(OUT) :: F
10424
INTEGER :: VARCOUNT
10425
!-------------------------------------------------------------------------------
10426
integer :: lstat
10427
10428
#ifdef HAVE_LUA
10429
L % tx(1:varcount) = T(1:varcount) ! this should be superfluous
10430
call lua_exec_fun(L, ptr % cvalue, 0, 1)
10431
F = lua_popnumber(LuaState)
10432
#else
10433
CALL Fatal('ElmerEvalLuaV', 'Lua not compiled in.')
10434
#endif
10435
!-------------------------------------------------------------------------------
10436
END SUBROUTINE ElmerEvalLuaS
10437
!-------------------------------------------------------------------------------
10438
10439
10440
#if defined DEVEL_LISTCOUNTER || defined DEVEL_LISTUSAGE
10441
10442
!------------------------------------------------------------------------------
10443
!> Go through the lists and for each lists show call counts.
10444
!------------------------------------------------------------------------------
10445
SUBROUTINE ReportListCounters( Model, ReportMode )
10446
TYPE(Model_t) :: Model
10447
INTEGER :: ReportMode
10448
10449
CHARACTER(LEN=MAX_NAME_LEN) :: dirname,filename
10450
INTEGER :: i, totcount, nelem, ReportUnit
10451
LOGICAL :: Unused, GotFile
10452
10453
IF(ReportMode == 1 ) THEN
10454
! Just initialize the lists from -1 to 0 such that only original keywords will be
10455
! reported in mode 2.
10456
GOTO 100
10457
END IF
10458
10459
filename = ListGetString( Model % Simulation,'List Counter File',GotFile )
10460
IF(.NOT. GotFile ) filename = '../listcounter.dat'
10461
10462
! We may toggle this to enable is disable automatic writing to file
10463
! For example, when we want to collect data automatically from tests.
10464
!GotFile = .TRUE.
10465
10466
IF( GotFile ) THEN
10467
CALL Info('ReportListCounters','Saving ListGet operations counts')
10468
ReportUnit = 10
10469
!IF( ParEnv % PEs > 1 ) THEN
10470
! filename = TRIM(filename)//'.'//I2S(ParEnv % MyPe)
10471
!END IF
10472
OPEN( 10,File=filename,STATUS='UNKNOWN',POSITION='APPEND' )
10473
CALL GETCWD(dirname)
10474
10475
! These are only for reference if writing lot of data to same file
10476
WRITE( ReportUnit,'(A)') 'Working directory: '//TRIM(dirname)
10477
nelem = Model % Mesh % NumberOfBulkElements
10478
WRITE( ReportUnit,'(T4,A)') 'Number of elements: '//I2S(nelem)
10479
WRITE( ReportUnit,'(T4,A)') 'Number of nodes: '//I2S(Model % Mesh % NumberOfNodes)
10480
ELSE
10481
! IF( ParEnv % MyPe /= 0) RETURN
10482
ReportUnit = 6
10483
END IF
10484
10485
! In the first round write the unused keywords
10486
! On the 2nd round write the keywords that
10487
Unused = .TRUE.
10488
totcount = 0
10489
10490
100 IF( ReportMode == 1 ) THEN
10491
CONTINUE
10492
ELSE IF( Unused ) THEN
10493
WRITE( ReportUnit,'(T4,A)') 'Unused keywords:'
10494
ELSE
10495
WRITE( ReportUnit,'(T4,A)') 'Used keywords:'
10496
END IF
10497
10498
CALL ReportList('Simulation', Model % Simulation, Unused )
10499
CALL ReportList('Constants', Model % Constants, Unused )
10500
DO i=1,Model % NumberOfEquations
10501
CALL ReportList('Equation '//I2S(i), Model % Equations(i) % Values, Unused )
10502
END DO
10503
DO i=1,Model % NumberOfComponents
10504
CALL ReportList('Component '//I2S(i), Model % Components(i) % Values, Unused )
10505
END DO
10506
DO i=1,Model % NumberOfBodyForces
10507
CALL ReportList('Body Force '//I2S(i), Model % BodyForces(i) % Values, Unused )
10508
END DO
10509
DO i=1,Model % NumberOfICs
10510
CALL ReportList('Initial Condition '//I2S(i), Model % ICs(i) % Values, Unused )
10511
END DO
10512
DO i=1,Model % NumberOfBCs
10513
CALL ReportList('Boundary Condition '//I2S(i), Model % BCs(i) % Values, Unused )
10514
END DO
10515
DO i=1,Model % NumberOfMaterials
10516
CALL ReportList('Material '//I2S(i), Model % Materials(i) % Values, Unused )
10517
END DO
10518
DO i=1,Model % NumberOfBoundaries
10519
CALL ReportList('Boundary '//I2S(i), Model % Boundaries(i) % Values, Unused )
10520
END DO
10521
DO i=1,Model % NumberOfSolvers
10522
CALL ReportList('Solver '//I2S(i), Model % Solvers(i) % Values, Unused )
10523
END DO
10524
10525
IF( ReportMode == 3 ) THEN
10526
IF( Unused ) THEN
10527
Unused = .FALSE.
10528
GOTO 100
10529
END IF
10530
CALL Info('ReportListCounters','List operations total count:'//I2S(totcount))
10531
END IF
10532
10533
IF (ReportMode /= 1) THEN
10534
IF( GotFile ) CLOSE(ReportUnit)
10535
END IF
10536
CONTAINS
10537
10538
10539
!------------------------------------------------------------------------------
10540
! Plot the number of times that the list entries have been called.
10541
!------------------------------------------------------------------------------
10542
SUBROUTINE ReportList( SectionName, List, Unused )
10543
TYPE(ValueList_t), POINTER :: List
10544
CHARACTER(LEN=*) :: SectionName
10545
LOGICAL :: Unused
10546
!------------------------------------------------------------------------------
10547
TYPE(ValueListEntry_t), POINTER :: ptr
10548
INTEGER :: n, m
10549
10550
IF(.NOT.ASSOCIATED(List)) RETURN
10551
10552
Ptr => List % Head
10553
DO WHILE( ASSOCIATED(ptr) )
10554
n = ptr % NameLen
10555
m = ptr % Counter
10556
10557
IF(ReportMode == 1 ) THEN
10558
! Change existing keywords tag from 0 to -1
10559
ptr % Counter = -1
10560
ELSE IF(ReportMode == 2 .AND. m == -1 ) THEN
10561
! Do not report "name" as it makes sense to have one.
10562
IF( ptr % Name == 'name' ) THEN
10563
CONTINUE
10564
ELSE
10565
WRITE( ReportUnit,'(T8,A,T30,A)') TRIM(SectionName),ptr % Name(1:n)
10566
END IF
10567
ELSE IF( ReportMode == 3 ) THEN
10568
IF( Unused .AND. m == 0 ) THEN
10569
WRITE( ReportUnit,'(T8,A,T30,A)') TRIM(SectionName),ptr % Name(1:n)
10570
ELSE IF(.NOT. Unused .AND. m > 0 ) THEN
10571
WRITE( ReportUnit,'(T8,A,T30,I0,T40,A)') TRIM(SectionName),m,ptr % Name(1:n)
10572
totcount = totcount + m
10573
END IF
10574
END IF
10575
ptr => ptr % Next
10576
END DO
10577
10578
END SUBROUTINE ReportList
10579
!------------------------------------------------------------------------------
10580
10581
END SUBROUTINE ReportListCounters
10582
!------------------------------------------------------------------------------
10583
10584
#else
10585
10586
SUBROUTINE ReportListCounters( Model )
10587
TYPE(Model_t) :: Model
10588
10589
CALL Info('ReportListCounter','List counters are not activated!')
10590
END SUBROUTINE ReportListCounters
10591
10592
#endif
10593
10594
10595
10596
10597
END MODULE Lists
10598
10599
!> \} ElmerLib
10600
10601