Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/UserFunctions/USF_ShapeFactor.F90
3196 views
1
!/*****************************************************************************/
2
! *
3
! * Elmer/Ice, a glaciological add-on to Elmer
4
! * http://elmerice.elmerfem.org
5
! *
6
! *
7
! * This program is free software; you can redistribute it and/or
8
! * modify it under the terms of the GNU General Public License
9
! * as published by the Free Software Foundation; either version 2
10
! * of the License, or (at your option) any later version.
11
! *
12
! * This program is distributed in the hope that it will be useful,
13
! * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
! * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
! * GNU General Public License for more details.
16
! *
17
! * You should have received a copy of the GNU General Public License
18
! * along with this program (in file fem/GPL-2); if not, write to the
19
! * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20
! * Boston, MA 02110-1301, USA.
21
! *
22
! *****************************************************************************/
23
! ******************************************************************************
24
! *
25
! * Authors: Olivier Gagliardini
26
! * Email:
27
! * Web: http://elmerice.elmerfem.org
28
! *
29
! * Original Date:
30
! *
31
! *****************************************************************************
32
!> Shape Factor user functions
33
!>
34
!> return the gravity force -g + (1-f)(g.t).t
35
!> where t is the tangent vector of the surface
36
!> end f is the shape factor
37
!> work only in 2D (no sense in 3D)
38
!> work for non-structured mesh
39
!> f can be given or calculated as a function of H(x,t) (height)
40
!> for different shape (rectangle, parabola, shelf)
41
FUNCTION ShapeFactorGravity_x ( Model, nodenumber, x) RESULT(gx)
42
USE Types
43
USE DefUtils
44
IMPLICIT NONE
45
TYPE(Model_t) :: Model
46
INTEGER :: nodenumber
47
REAL(KIND=dp) :: x, gx, ShapeFactorGravity
48
49
gx = ShapeFactorGravity ( Model, nodenumber, x, 1 )
50
51
52
END FUNCTION ShapeFactorGravity_x
53
54
FUNCTION ShapeFactorGravity_y ( Model, nodenumber, x) RESULT(gy)
55
USE Types
56
USE DefUtils
57
IMPLICIT NONE
58
TYPE(Model_t) :: Model
59
INTEGER :: nodenumber
60
REAL(KIND=dp) :: x, gy, ShapeFactorGravity
61
62
gy = ShapeFactorGravity ( Model, nodenumber, x, 2 )
63
64
END FUNCTION ShapeFactorGravity_y
65
66
67
68
69
FUNCTION ShapeFactorGravity ( Model, nodenumber, x, axis ) RESULT(gi)
70
USE types
71
USE GeneralUtils
72
USE CoordinateSystems
73
USE SolverUtils
74
USE ElementDescription
75
USE DefUtils
76
IMPLICIT NONE
77
TYPE(Model_t) :: Model
78
INTEGER :: nodenumber, axis
79
REAL(KIND=dp) :: x, gi
80
81
TYPE(Nodes_t), SAVE :: Nodes
82
TYPE(variable_t), POINTER :: Timevar
83
TYPE(Element_t), POINTER :: BoundaryElement, BCElement, CurElement, ParentElement
84
TYPE(ValueList_t), POINTER :: BodyForce, BC
85
86
87
REAL(KIND=dp), ALLOCATABLE :: zs(:), xs(:), ts(:,:), zb(:), xb(:)
88
REAL(KIND=dp), TARGET, ALLOCATABLE :: z2s(:), z2b(:), ts2x(:), ts2y(:), para2(:)
89
REAL(KIND=dp), DIMENSION(:), POINTER :: z2s_p, z2b_p, ts2x_p, ts2y_p, para2_p
90
REAL(KIND=dp), ALLOCATABLE :: auxReal(:), para(:)
91
REAL(KIND=dp) :: t, t0, told, Bu, Bv, f, afactor, width, H, w, NVelo
92
REAL(KIND=dp) :: g(2), tangent(2), normal(3), Velo(2)
93
94
INTEGER, ALLOCATABLE :: ind(:), NodesOnSurface(:), NodesOnBed(:)
95
INTEGER, ALLOCATABLE :: TempS(:), TempB(:)
96
INTEGER :: Ns, Nb
97
INTEGER ::i, j, n, k, p, DIM
98
99
LOGICAL :: FirstTime = .TRUE., NewTime, GotIt
100
LOGICAL :: Parabola, Rectangle, Computed=.TRUE.
101
LOGICAL :: Bedrock, Surface
102
103
!--------------------------------------------
104
! Parameter for the shape function definition
105
! f(w) = 2/ (n pi) sum_i=1^n ATAN(a(i) x w^i)
106
!--------------------------------------------
107
INTEGER, PARAMETER :: nr=6, np=1
108
REAL(KIND=dp), PARAMETER :: ap(np) = (/0.814589_dp/), &
109
ar(nr) = (/5.30904_dp,0.0934244_dp,3.94177_dp,74.6014_dp,0.0475342_dp,1.35021_dp/)
110
111
SAVE told, t0, FirstTime, NewTime, g
112
SAVE zs, xs, ts, zb, xb, Ns, Nb, para, auxReal
113
SAVE z2s, z2b, ts2x, ts2y, para2
114
SAVE Parabola, Rectangle, Computed
115
SAVE NodesOnSurface, NodesOnBed, TempS, TempB
116
117
Timevar => VariableGet( Model % Variables,'Time')
118
t = TimeVar % Values(1)
119
120
IF (FirstTime) THEN
121
! STOP if we are not solving a 2D flow line problem
122
DIM = CoordinateSystemDimension()
123
IF ( DIM /= 2 ) THEN
124
CALL FATAL('ShapeFactorGravity','Work only for 2D flow line problem')
125
END IF
126
127
FirstTime = .FALSE.
128
NewTime = .TRUE.
129
told = t
130
t0 = t
131
132
n = Model % MaxElementNodes
133
ALLOCATE( auxReal(n) )
134
135
BodyForce => GetBodyForce()
136
137
!-------------------------
138
! Get the gravity vector g
139
!-------------------------
140
g(1) = GetConstReal( BodyForce, 'Shape Gravity 1', GotIt )
141
g(2) = GetConstReal( BodyForce, 'Shape Gravity 2', GotIt )
142
IF ( .Not.GotIt ) CALL FATAL('ShapeFactorGravity', &
143
'Gravity vector must be specified')
144
145
!---------------------------------------------
146
! Determine how is calculated the shape factor
147
!---------------------------------------------
148
Parabola = GetLogical( BodyForce, 'Parabola Shape', GotIt)
149
IF (.Not.GotIt) Parabola = .FALSE.
150
Rectangle = GetLogical( BodyForce, 'Rectangle Shape', GotIt)
151
IF (.Not.GotIt) Rectangle = .FALSE.
152
IF (Rectangle.AND.Parabola) CALL FATAL('ShapeFactorGravity', &
153
'Make a choice between Parabola or Rectangle shapes')
154
IF ((.Not.Rectangle).AND.(.Not.Parabola)) THEN
155
Computed = .FALSE.
156
CurElement => Model % CurrentElement
157
n = CurElement % Type % NumberOfNodes
158
auxReal(1:n) = GetReal( BodyForce, &
159
'Shape Factor', GotIt )
160
IF ( .Not.GotIt ) CALL FATAL('ShapeFactorGravity', &
161
'Shape Factor must be given or Computed')
162
END IF
163
164
165
!-------------------------------------------
166
! Number of nodes on the bed and the surface
167
!-------------------------------------------
168
CurElement => Model % CurrentElement
169
Ns = 1
170
Nb = 1
171
DO p = 1, Model % NumberOfBoundaryElements
172
BCElement => GetBoundaryElement(p)
173
BC => GetBC( BCElement )
174
IF( GetElementFamily(BCElement) == 1 ) CYCLE
175
Surface = .FALSE.
176
Bedrock = .FALSE.
177
Surface = GetLogical( BC, 'Shape Surface', GotIt)
178
Bedrock = GetLogical( BC, 'Shape Bedrock', GotIt)
179
IF (Surface) THEN
180
n = BCElement % Type % NumberOfNodes
181
Ns = Ns + n - 1
182
ELSE IF (Bedrock) THEN
183
n = BCElement % Type % NumberOfNodes
184
Nb = Nb + n - 1
185
END IF
186
END DO
187
Model % CurrentElement => CurElement
188
189
IF ((Ns==0).OR.(Nb==0)) CALL FATAL('ShapeFactorGravity', &
190
'Shape Surface and/or Shape Bedrock not defined')
191
192
ALLOCATE ( zs(Ns), ts(2,Ns), xs(Ns), xb(Nb), zb(Nb) )
193
ALLOCATE (z2s(Ns), z2b(Ns), ts2x(Ns), ts2y(Ns) )
194
ALLOCATE ( NodesOnSurface(Ns), NodesOnBed(Nb), TempS(Ns), TempB(Nb) )
195
IF (Computed) ALLOCATE( para(Ns), para2(Ns) )
196
197
198
!-----------------------------------------------------
199
! Store the nodes number on the bed and on the surface
200
!-----------------------------------------------------
201
CurElement => Model % CurrentElement
202
Ns = 0
203
Nb = 0
204
NodesOnSurface = 0
205
NodesOnBed = 0
206
DO p = 1, Model % NumberOfBoundaryElements
207
BCElement => GetBoundaryElement(p)
208
BC => GetBC( BCElement )
209
IF( GetElementFamily(BCElement) == 1 ) CYCLE
210
Surface = .FALSE.
211
Bedrock = .FALSE.
212
Surface = GetLogical( BC, 'Shape Surface', GotIt)
213
Bedrock = GetLogical( BC, 'Shape Bedrock', GotIt)
214
IF (Surface) THEN
215
n = BCElement % Type % NumberOfNodes
216
DO i = 1, n
217
j = BCElement % NodeIndexes(i)
218
IF (.NOT.ANY(NodesOnSurface == j )) THEN
219
Ns = Ns + 1
220
NodesOnSurface(Ns) = j
221
xs(Ns) = Model % Nodes % x( j )
222
END IF
223
END DO
224
ELSE IF (Bedrock) THEN
225
n = BCElement % Type % NumberOfNodes
226
DO i = 1, n
227
j = BCElement % NodeIndexes(i)
228
IF (.NOT.ANY(NodesOnBed == j )) THEN
229
Nb = Nb + 1
230
NodesOnBed(Nb) = j
231
xb(Nb) = Model % Nodes % x( j )
232
END IF
233
END DO
234
END IF
235
END DO
236
Model % CurrentElement => CurElement
237
238
!------------------------------------------
239
! Get ordered NodesOnSurface and NodesOnBed
240
! SortD : sort in increase order
241
!------------------------------------------
242
ALLOCATE (ind(Ns))
243
ind = (/(i,i=1,Ns)/)
244
CALL SortD(Ns,xs,ind)
245
NodesOnSurface = NodesOnSurface(ind)
246
DEALLOCATE(ind)
247
ALLOCATE (ind(Nb))
248
ind = (/(i,i=1,Nb)/)
249
CALL SortD(Nb,xb,ind)
250
NodesOnBed = NodesOnBed(ind)
251
DEALLOCATE(ind)
252
253
!----------------------------------------
254
! If Computed
255
! Get the width of the rectangle channel
256
! Get the afactor of the parabola channel
257
!----------------------------------------
258
IF (Computed) THEN
259
CurElement => Model % CurrentElement
260
DO p = 1, Model % NumberOfBoundaryElements
261
BCElement => GetBoundaryElement(p)
262
BC => GetBC( BCElement )
263
IF( GetElementFamily(BCElement) == 1 ) CYCLE
264
Surface = .FALSE.
265
Surface = GetLogical( BC, 'Shape Surface', GotIt)
266
IF (Surface) THEN
267
n = BCElement % Type % NumberOfNodes
268
IF (Parabola) THEN
269
auxReal(1:n) = GetReal( BodyForce, &
270
'Parabola aFactor', GotIt )
271
IF (.Not.GotIt) CALL FATAL('ShapeFactorGravity', &
272
'Parabola aFactor must be given for Parabola shape')
273
ELSE IF (Rectangle) THEN
274
auxReal(1:n) = GetReal( BodyForce, &
275
'Rectangle Width', GotIt )
276
IF ((.Not.GotIt).AND.Rectangle) CALL FATAL('ShapeFactorGravity', &
277
'Rectangle Width must be given for Rectangle shape')
278
END IF
279
DO i = 1, n
280
j = BCElement % NodeIndexes(i)
281
TempS = 0
282
WHERE (NodesOnSurface==j) TempS = 1
283
k = MAXLOC(TempS, dim=1)
284
para(k) = auxReal(i)
285
END DO
286
END IF
287
END DO
288
Model % CurrentElement => CurElement
289
END IF
290
291
ELSE
292
IF (t > told) THEN
293
NewTime = .TRUE.
294
told = t
295
END IF
296
ENDIF
297
298
IF (NewTime) THEN
299
NewTime = .FALSE.
300
!---------------------------------------------
301
! Nodal value of zs, zb, tangent for that time
302
!---------------------------------------------
303
ts = 0.0_dp
304
CurElement => Model % CurrentElement
305
DO p = 1, Model % NumberOfBoundaryElements
306
BCElement => GetBoundaryElement(p)
307
BC => GetBC( BCElement )
308
IF( GetElementFamily(BCElement) == 1 ) CYCLE
309
Surface = .FALSE.
310
Bedrock = .FALSE.
311
Surface = GetLogical( BC, 'Shape Surface', GotIt)
312
Bedrock = GetLogical( BC, 'Shape Bedrock', GotIt)
313
IF (Surface) THEN
314
n = BCElement % Type % NumberOfNodes
315
CALL GetElementNodes( Nodes , BCElement )
316
DO i = 1,n
317
j = BCElement % NodeIndexes( i )
318
Bu = BCElement % Type % NodeU(i)
319
Bv = 0.0D0
320
Normal = NormalVector(BCElement, Nodes, Bu, Bv, .TRUE.)
321
TempS = 0
322
WHERE (NodesOnSurface==j) TempS = 1
323
k = MAXLOC(TempS, dim=1)
324
ts(1,k) = ts(1,k) + Normal(2)
325
ts(2,k) = ts(2,k) - Normal(1)
326
xs(k) = Model % Nodes % x(j)
327
zs(k) = Model % Nodes % y(j)
328
END DO
329
ELSE IF(Bedrock) THEN
330
n = BCElement % Type % NumberOfNodes
331
DO i = 1,n
332
j = BCElement % NodeIndexes( i )
333
TempB = 0
334
WHERE (NodesOnBed==j) TempB = 1
335
k = MAXLOC(TempB, dim=1)
336
xb(k) = Model % Nodes % x(j)
337
zb(k) = Model % Nodes % y(j)
338
END DO
339
END IF
340
END DO
341
342
DO i=1, Ns
343
ts(:,i) = ts(:,i) / SQRT(SUM(ts(:,i)**2.0))
344
END DO
345
Model % CurrentElement => CurElement
346
347
!-----------------------------------
348
! Construct the spline interpolation
349
!-----------------------------------
350
CALL CubicSpline(Ns,xs,zs,z2s)
351
CALL CubicSpline(Nb,xb,zb,z2b)
352
CALL CubicSpline(Ns,xs,ts(1,:),ts2x)
353
CALL CubicSpline(Ns,xs,ts(2,:),ts2y)
354
IF (Computed) CALL CubicSpline(Ns,xs,para,para2)
355
356
ENDIF ! new dt
357
358
359
BodyForce => GetBodyForce()
360
CurElement => Model % CurrentElement
361
n = CurElement % Type % NumberOfNodes
362
!-----------------------
363
! Interpolate for that x
364
!-----------------------
365
x = Model % Nodes % x ( nodenumber)
366
IF (Computed) THEN
367
z2s_p => z2s
368
z2b_p => z2b
369
H = InterpolateCurve(xs,zs,x,z2s_p) - InterpolateCurve(xb,zb,x,z2b_p)
370
IF (Parabola) THEN
371
para2_p => para2
372
afactor = InterpolateCurve(xs,para,x,para2_p)
373
IF ((H>0.0).AND.(afactor>0.0)) THEN
374
w = 1.0/SQRT(H*afactor)
375
f = 0.0_dp
376
DO i=1, np
377
f = f + ATAN(ap(i)*w**i)
378
END DO
379
f = 2.0*f/(np*pi)
380
ELSE
381
f = 1.0
382
END IF
383
ELSE IF (Rectangle) THEN
384
para2_p => para2
385
width = InterpolateCurve(xs,para,x,para2_p)
386
IF (H>0.0) THEN
387
w = width / (2.0*H)
388
f = 0.0_dp
389
DO i=1, nr
390
f = f + ATAN(ar(i)*w**i)
391
END DO
392
f = 2.0*f/(nr*pi)
393
ELSE
394
f = 1.0
395
END IF
396
END IF
397
ELSE
398
!------------------------------------
399
! Get the Shape factor for that nodes
400
!------------------------------------
401
auxReal(1:n) = GetReal( BodyForce, &
402
'Shape Factor', GotIt )
403
DO i=1, n
404
j = CurElement % NodeIndexes (i)
405
IF (nodenumber == j) EXIT
406
END DO
407
f = auxReal(i)
408
END IF
409
410
ts2x_p => ts2x
411
ts2y_p => ts2y
412
tangent(1) = InterpolateCurve(xs,ts(1,:),x,ts2x_p)
413
tangent(2) = InterpolateCurve(xs,ts(2,:),x,ts2y_p)
414
tangent = tangent / SQRT(SUM(tangent**2.0))
415
416
gi = g(axis) - (1.0 - f) * SUM(g*tangent) * tangent(axis)
417
418
419
420
END FUNCTION ShapeFactorGravity
421
422
423