Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/UserFunctions/USF_Sliding.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, Ga¨el Durand, Thomas Zwinger
26
! * Email:
27
! * Web: http://elmerice.elmerfem.org
28
! *
29
! * Original Date:
30
! * 2007/10/25. Gael Durand
31
! * 2008/04/06 OG 2D -> 3D
32
! * 2009/05/18 OG FirstTime in the SAVE !
33
! *****************************************************************************
34
!> USF_Sliding.f90
35
!>
36
!>
37
!> Gives the basal drag for different sliding law
38
!>
39
!> (1) Sliding_Weertman
40
!> Need some inputs in the sif file.
41
!> Parameters: Weertman Friction Coefficient -> C
42
!> Weertman Exponent -> m
43
!> Weertman Linear Velocity -> ut0
44
!>
45
!> Compute the Bdrag coefficient such as tau_b = Bdrag ub
46
!> for the non-linear Weertman law tau_b = C ub^m
47
!> To linearize the Weertman law, we can distinguish 4 cases:
48
!> 1/ ut=0 , tau_b=0 => Bdrag = infinity (no sliding, first step)
49
!> 2/ ut=0 , tau_b =/0 => Bdrag = C^1/m tau_b^(1-1/m)
50
!> 3/ ut=/0 , tau_b=0 => Bdrag = Cub^(m-1)
51
!> 4/ ut=/0 , tau_b=/0 => case 3
52
!> For cases 3 and 4, if ut < ut0, Bdrag = C ut0^{m-1}
53
!>
54
!>
55
!> (2) Friction_Coulomb Sliding Gag JGR 2007
56
!> Need some inputs in the sif file.
57
!> Parameters: Friction Law Sliding Coefficient -> As
58
!> Friction Law Post-Peak Exponent -> q >= 1
59
!> Friction Law Maximum Value -> C ~ max bed slope
60
!> Friction Law Linear Velocity -> ut0
61
FUNCTION Sliding_Weertman (Model, nodenumber, x) RESULT(Bdrag)
62
63
USE types
64
USE CoordinateSystems
65
USE SolverUtils
66
USE ElementDescription
67
USE DefUtils
68
IMPLICIT NONE
69
TYPE(Model_t) :: Model
70
REAL (KIND=dp) :: y , x
71
INTEGER :: nodenumber
72
73
TYPE(ValueList_t), POINTER :: BC
74
TYPE(Variable_t), POINTER :: NormalVar, FlowVariable
75
REAL(KIND=dp), POINTER :: NormalValues(:), FlowValues(:)
76
INTEGER, POINTER :: NormalPerm(:), FlowPerm(:)
77
INTEGER :: DIM, i, j, n
78
REAL (KIND=dp) :: C, m, Bdrag
79
REAL (KIND=dp) :: ut, un, ut0
80
REAL (KIND=dp), ALLOCATABLE :: normal(:), velo(:), AuxReal(:)
81
LOGICAL :: GotIt, FirstTime = .TRUE., SSA = .FALSE., UnFoundFatal=.TRUE.
82
83
CHARACTER(LEN=MAX_NAME_LEN) :: FlowSolverName
84
85
SAVE :: normal, velo, DIM, SSA
86
SAVE :: FlowSolverName, FirstTime
87
88
IF (FirstTime) THEN
89
FirstTime = .FALSE.
90
DIM = CoordinateSystemDimension()
91
n = Model % MaxElementNodes
92
IF ((DIM == 2).OR.(DIM == 3)) THEN
93
ALLOCATE(normal(DIM), velo(DIM))
94
ELSE
95
CALL FATAL('USF_sliding', 'Bad dimension of the problem')
96
END IF
97
98
! BC => GetBC(Model % CurrentElement)
99
FlowSolverName = GetString( Model % Solver % Values , 'Flow Solver Name', GotIt )
100
IF (.NOT.Gotit) FlowSolverName = 'Flow Solution'
101
SELECT CASE (FlowSolverName)
102
CASE ('ssabasalflow')
103
SSA = .TRUE.
104
END SELECT
105
WRITE(Message,*)&
106
'Flow Solver Name:', TRIM(FlowSolverName),' SSA:',SSA
107
CALL INFO('Sliding_Weertman',Message,Level=3)
108
END IF
109
110
!Read the coefficients C and m in the sif file
111
BC => GetBC(Model % CurrentElement)
112
IF (.NOT.ASSOCIATED(BC))THEN
113
CALL Fatal('Sliding_Weertman', 'No BC Found')
114
END IF
115
116
n = GetElementNOFNodes()
117
ALLOCATE (auxReal(n))
118
auxReal(1:n) = GetReal( BC, 'Weertman Friction Coefficient', GotIt )
119
IF (.NOT.GotIt) THEN
120
CALL FATAL('USF_sliding', 'Need a Friction Coefficient for the Weertman sliding law')
121
END IF
122
DO i=1,n
123
IF (nodenumber == Model % CurrentElement % NodeIndexes( i )) EXIT
124
END DO
125
C = auxReal(i)
126
DEALLOCATE(auxReal)
127
128
m = GetConstReal( BC, 'Weertman Exponent', GotIt )
129
IF (.NOT.GotIt) THEN
130
CALL FATAL('USF_sliding', 'Need an Exponent for the Weertman sliding law')
131
END IF
132
133
ut0 = GetConstReal( BC, 'Weertman Linear Velocity', GotIt )
134
IF (.NOT.GotIt) THEN
135
CALL FATAL('USF_sliding', 'Need a Linear Velocity for the Weertman sliding law')
136
END IF
137
138
! Get the variables to compute ut
139
FlowVariable => VariableGet( Model % Variables, FlowSolverName,UnFoundFatal=UnFoundFatal)
140
FlowPerm => FlowVariable % Perm
141
FlowValues => FlowVariable % Values
142
143
! NS, AIFlow cases
144
IF (.NOT.SSA) THEN
145
! Get the variable to compute the normal
146
NormalVar => VariableGet(Model % Variables,'Normal Vector',UnFoundFatal=UnFoundFatal)
147
NormalPerm => NormalVar % Perm
148
NormalValues => NormalVar % Values
149
150
DO i=1, DIM
151
normal(i) = -NormalValues(DIM*(NormalPerm(Nodenumber)-1) + i)
152
velo(i) = FlowValues( (DIM+1)*(FlowPerm(Nodenumber)-1) + i )
153
END DO
154
un = SUM(velo(1:DIM)*normal(1:DIM))
155
ut = SQRT( SUM( (velo(1:DIM)-un*normal(1:DIM))**2.0 ) )
156
! SSA Flow case
157
ELSE
158
DO i=1, DIM-1
159
velo(i) = FlowValues( (DIM-1)*(FlowPerm(Nodenumber)-1) + i )
160
END DO
161
ut = SQRT(SUM( velo(1:DIM-1)**2.0 ))
162
END IF
163
164
ut = MAX(ut,ut0)
165
Bdrag = MIN(C * ut**(m-1.0),1.0e20)
166
END FUNCTION Sliding_Weertman
167
168
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
169
!> (2) Sliding Gag JGR 2007
170
!>
171
!> Gagliardini, Cohen, Raback and Zwinger, 2007. Finite-Element Modelling of
172
!> Subglacial Cavities and Related Friction Law. J. of Geophys. Res., Earth
173
!> Surface, 112, F02027
174
!>
175
!> Need some inputs in the sif file.
176
!> Parameters: Friction Law Sliding Coefficient -> As
177
!> Friction Law Post-Peak Exponent -> q >= 1
178
!> Friction Law Maximum Value -> C ~ max bed slope
179
!> Friction Law Linear Velocity -> ut0
180
!> Friction Law PowerLaw Exponent -> m = (n Glen's law)
181
!>
182
!> Water Pressure (BC) (Compressive - positive)
183
!>
184
!> tau_b = C.N.[ X . ub^-n / (1 + a.X^q) ]^1/n . ub
185
!> with a = (q-1)^(q-1) / q^q and X = ub / (C^n N^n As)
186
!>
187
!> => Bdrag = C.N.[ X . ub^-n / (1 + a.X^q) ]^1/n
188
FUNCTION Friction_Coulomb (Model, nodenumber, y) RESULT(Bdrag)
189
190
USE types
191
USE CoordinateSystems
192
USE SolverUtils
193
USE ElementDescription
194
USE DefUtils
195
IMPLICIT NONE
196
TYPE(Model_t) :: Model
197
REAL (KIND=dp) :: y , x
198
INTEGER :: nodenumber
199
200
TYPE(ValueList_t), POINTER :: BC, Material
201
TYPE(Variable_t), POINTER :: TimeVar, NVariable, StressVariable, NormalVar, FlowVariable
202
TYPE(Element_t), POINTER :: BoundaryElement, ParentElement
203
REAL(KIND=dp), POINTER :: StressValues(:), NormalValues(:), FlowValues(:)
204
REAL(KIND=dp), POINTER :: NValues(:)
205
INTEGER, POINTER :: StressPerm(:), NormalPerm(:), FlowPerm(:), NPerm(:)
206
INTEGER :: DIM, i, j, Ind(3,3), n, other_body_id
207
REAL (KIND=dp) :: C, m, Bdrag, As, Ne, q, Xi, a, Pw, Pice
208
REAL (KIND=dp) :: Snt, Snn, ut, un, ut0, t, t0
209
LOGICAL :: GotIt, FirstTime = .TRUE., Cauchy, UnFoundFatal
210
REAL (KIND=dp), ALLOCATABLE :: Sig(:,:), normal(:), velo(:), Sn(:), AuxReal(:)
211
212
SAVE :: Sig, normal, velo, DIM, Ind, Sn
213
SAVE :: t0, FirstTime
214
215
TimeVar => VariableGet( Model % Variables,'Time')
216
t = TimeVar % Values(1)
217
218
IF (FirstTime) THEN
219
FirstTime = .FALSE.
220
t0 = t
221
DIM = CoordinateSystemDimension()
222
IF ((DIM == 2).OR.(DIM == 3)) THEN
223
ALLOCATE(Sig(DIM,DIM),normal(DIM), velo(DIM), Sn(DIM))
224
ELSE
225
CALL FATAL('Friction_Coulomb', 'Bad dimension of the problem')
226
END IF
227
Do i=1, 3
228
Ind(i,i) = i
229
END DO
230
Ind(1,2) = 4
231
Ind(2,1) = 4
232
Ind(2,3) = 5
233
Ind(3,2) = 5
234
Ind(3,1) = 6
235
Ind(1,3) = 6
236
END IF
237
238
!Read the coefficients As, C, q, and m=1/n in the BC Section
239
BoundaryElement => Model % CurrentElement
240
BC => GetBC(BoundaryElement)
241
n = GetElementNOFNodes()
242
IF (.NOT.ASSOCIATED(BC))THEN
243
CALL Fatal('Friction_Coulomb', 'No BC Found')
244
END IF
245
246
! Friction Law Sliding Coefficient -> As
247
ALLOCATE (auxreal(n))
248
auxReal(1:n) = GetReal( BC, 'Friction Law Sliding Coefficient', GotIt )
249
IF (.NOT.GotIt) THEN
250
CALL FATAL('Friction_Coulomb', 'Need a Friction Law Sliding Coefficient for the Coulomb Friction Law')
251
END IF
252
DO i=1, n
253
IF (NodeNumber== BoundaryElement % NodeIndexes( i )) EXIT
254
END DO
255
As = auxReal(i)
256
257
! Friction Law Post-Peak Exponent -> q >= 1
258
auxReal(1:n) = GetReal( BC, 'Friction Law Post-Peak Exponent', GotIt )
259
IF (.NOT.GotIt) THEN
260
CALL FATAL('Friction_Coulomb', 'Need a Friction Law Post-Peak Exponent &
261
& (>= 1) for the Coulomb Friction Law')
262
END IF
263
DO i=1, n
264
IF (NodeNumber== BoundaryElement % NodeIndexes( i )) EXIT
265
END DO
266
q = auxReal(i)
267
268
a = (q-1.0)**(q-1.0) / q**q
269
270
! Friction Law Maximum Value -> C ~ max bed slope
271
auxReal(1:n) = GetReal( BC, 'Friction Law Maximum Value', GotIt )
272
IF (.NOT.GotIt) THEN
273
CALL FATAL('Friction_Coulomb', 'Need a Friction Law Maximum Value &
274
& (~ Max Bed Slope) for the Coulomb Friction Law')
275
END IF
276
DO i=1, n
277
IF (NodeNumber== BoundaryElement % NodeIndexes( i )) EXIT
278
END DO
279
C = auxReal(i)
280
281
282
! Friction Law Linear Velocity -> ut0
283
ut0 = GetConstReal( BC, 'Friction Law Linear Velocity', GotIt )
284
IF (.NOT.GotIt) THEN
285
CALL FATAL('Friction_Coulomb', 'Need a Friction Law Linear Velocity for the Coulomb Friction Law ')
286
END IF
287
!
288
! friction Law PowerLaw Exponent m
289
m = GetConstReal( BC, 'Friction Law PowerLaw Exponent', GotIt )
290
IF (.NOT.GotIt) THEN
291
CALL FATAL('Friction_Coulomb', 'Need a Friction Law PowerLaw Exponent &
292
& (= n Glen law) for the Coulomb Friction Law')
293
END IF
294
!
295
! Effective Pressure is either given as a variable
296
! or computed as N = -Snn - pw
297
! Get the effective pressure
298
! If NVariable does not exist, N will be computed as N = -Snn - pw
299
NVariable => VariableGet( Model % Variables, 'Effective Pressure' )
300
IF ( ASSOCIATED( NVariable ) ) THEN
301
NPerm => NVariable % Perm
302
NValues => NVariable % Values
303
304
ELSE
305
! Get the water Pressure from the Stokes keyword 'External Pressure'
306
! Use the convention for the water pressure Pw > 0 => Compression
307
auxReal(1:n) = GetReal( BC, 'External Pressure', GotIt )
308
IF (.NOT.GotIt) THEN
309
CALL FATAL('Friction_Coulomb', 'Need External Pressure &
310
& Or Variable Effective Pressure')
311
END IF
312
DO i=1, n
313
IF (NodeNumber== BoundaryElement % NodeIndexes( i )) EXIT
314
END DO
315
! Because the convention is External Pressure < 0 => Compression,
316
! need to change the sign
317
Pw = -auxReal(i)
318
319
! Get the variables to compute tau_b
320
StressVariable => VariableGet( Model % Variables, 'Stress',UnFoundFatal=UnFoundFatal)
321
StressPerm => StressVariable % Perm
322
StressValues => StressVariable % Values
323
!
324
! Cauchy or deviatoric stresses ?
325
!
326
other_body_id = BoundaryElement % BoundaryInfo % outbody
327
IF (other_body_id < 1) THEN ! only one body in calculation
328
ParentElement => BoundaryElement % BoundaryInfo % Right
329
IF ( .NOT. ASSOCIATED(ParentElement) ) ParentElement => BoundaryElement % BoundaryInfo % Left
330
ELSE ! we are dealing with a body-body boundary and assume that the normal is pointing outwards
331
ParentElement => BoundaryElement % BoundaryInfo % Right
332
IF (ParentElement % BodyId == other_body_id) ParentElement => BoundaryElement % BoundaryInfo % Left
333
END IF
334
335
Material => GetMaterial(ParentElement)
336
Cauchy = ListGetLogical( Material , 'Cauchy', Gotit )
337
338
END IF
339
DEALLOCATE(auxReal)
340
341
! Get the flow variables to compute ut
342
FlowVariable => VariableGet( Model % Variables, 'Flow Solution',UnFoundFatal=UnFoundFatal)
343
FlowPerm => FlowVariable % Perm
344
FlowValues => FlowVariable % Values
345
346
! Get the normal variable to compute the normal
347
NormalVar => VariableGet(Model % Variables,'Normal Vector',UnFoundFatal=UnFoundFatal)
348
NormalPerm => NormalVar % Perm
349
NormalValues => NormalVar % Values
350
351
DO i=1, DIM
352
normal(i) = -NormalValues(DIM*(NormalPerm(Nodenumber)-1) + i)
353
velo(i) = FlowValues( (DIM+1)*(FlowPerm(Nodenumber)-1) + i )
354
END DO
355
356
un = SUM(velo(1:DIM)*normal(1:DIM))
357
ut = SQRT( SUM( (velo(1:DIM)-un*normal(1:DIM))**2.0 ) )
358
359
! Compute Effective Pressure Ne
360
! Effective pressure N >=0
361
IF ( ASSOCIATED( NVariable ) ) THEN
362
Ne = NValues(NPerm(Nodenumber))
363
ELSE
364
DO i=1, DIM
365
DO j= 1, DIM
366
Sig(i,j) = &
367
StressValues( 2*DIM *(StressPerm(Nodenumber)-1) + Ind(i,j) )
368
END DO
369
END DO
370
! Stress vector Sn
371
DO i=1, DIM
372
Sn(i) = SUM(Sig(i,1:DIM)*normal(1:DIM))
373
END DO
374
! Normal stress (still Cauchy or deviatoric)
375
Snn = SUM( Sn(1:DIM) * normal(1:DIM) )
376
! Isotropic ice pressure
377
Pice = FlowValues((DIM+1)*FlowPerm(Nodenumber))
378
379
IF (Cauchy) THEN
380
! At first time Snn = 0 and should be approximated by -pi
381
IF (ABS(Snn) < 1.0e-10*ABS(Pice)) Snn = -Pice
382
ELSE
383
Snn = Snn - Pice
384
END IF
385
386
! Convention is such that Snn should be negative (compressive)
387
Ne = -Snn -Pw
388
ENDIF
389
390
Bdrag = 0.0_dp
391
IF ( Ne>0 ) THEN
392
ut = MAX(ut,ut0)
393
Xi = ut / (As * (C*Ne)**m )
394
Xi = MIN(Xi,1.0e20_dp)
395
ELSE
396
Xi = 1.0e20_dp
397
WRITE(Message,*) '!!! Ne <=0, nodenumber',nodenumber, Ne
398
CALL INFO ("Friction_Coulomb", Message, Level=9)
399
! write(*,*)'!!! Ne <=0, nodenumber',nodenumber, Ne
400
Ne = 0.0
401
END IF
402
403
Bdrag = C*Ne * ((Xi * ut**(-m)) / ( 1.0 + a * Xi**q))**(1.0/m)
404
Bdrag = MIN(Bdrag,1.0e20_dp)
405
406
! Stress may be not known at first time / or first steady iteration
407
IF ((t==t0).AND.(.Not.ASSOCIATED( NVariable )).AND.(Snn.GE.0.0_dp)) Bdrag = 1.0e20
408
END FUNCTION Friction_Coulomb
409
410
! Sliding after Budd et al 1984, Annals of Glaciology 5, page 29-36.
411
!
412
! Magnitude of sliding is:
413
!
414
! tau_b = C.{u_b}^{m}*Zab^{q}
415
!
416
! where Zab is height above buoyancy and C, m and q respectively are
417
! given in the sif by:
418
! Budd Friction Coefficient = Real 2.412579e-2
419
! Budd Velocity Exponent = Real $1.0/3.0
420
! Budd Zab Exponent = Real 2.0
421
!
422
! Budd Floatation = Logical False
423
! If this is set to true then the height above buoyancy will be based
424
! on the floatation condition instead of inferred from the effective
425
! pressure (i.e. depth is used instead of normal stress). Default is
426
! false.
427
!
428
! Linearisation for small velocity is used, similar to Weertman
429
! above:
430
! Budd Linear Velocity = Real 0.00001
431
!
432
! Slip coefficient in Elmer is given as
433
! C.{u_b}^{m - 1}*Zab^{q}
434
!
435
!
436
! Pre-requisites are as for EffectivePressure below, plus:
437
! "Budd Ice Density" and "Budd Gravity" need to be defined in the
438
! relevant (basal) boundary condition, in addition to the four
439
! parameters above.
440
!
441
FUNCTION Sliding_Budd (Model, nodenumber, z) RESULT(Bdrag)
442
443
USE types
444
USE CoordinateSystems
445
USE SolverUtils
446
USE ElementDescription
447
USE DefUtils
448
449
IMPLICIT NONE
450
451
TYPE(Model_t) :: Model
452
REAL (KIND=dp) :: z
453
INTEGER :: nodenumber
454
455
REAL (KIND=dp) :: Bdrag
456
457
REAL (KIND=dp), ALLOCATABLE :: normal(:), velo(:), BuddFrictionCoeff(:)
458
TYPE(ValueList_t), POINTER :: BC, ParentMaterial
459
TYPE(Variable_t), POINTER :: NormalVar, FlowVariable, Hvar
460
TYPE(Element_t), POINTER :: parentElement, BoundaryElement
461
REAL(KIND=dp), POINTER :: NormalValues(:), FlowValues(:), HValues(:), WeertCoefValues(:)
462
TYPE(Variable_t), POINTER :: coefVar, WeertCoefVar
463
REAL(KIND=dp), POINTER :: coefValues(:)
464
INTEGER, POINTER :: coefPerm(:)
465
INTEGER, POINTER :: NormalPerm(:), FlowPerm(:), HPerm(:), WeertCoefPerm(:)
466
INTEGER :: DIM, i, body_id, other_body_id, material_id, elementNbNodes,elementNodeNumber
467
REAL (KIND=dp) :: m, q, g, rhoi, Zab, Zab_offset, ep, sl, H, rhow
468
REAL (KIND=dp) :: C, ut, un, ut0, WeertExp, Cw
469
LOGICAL :: GotIt, FirstTime = .TRUE., SSA = .FALSE., UseFloatation = .FALSE., H_scaling
470
LOGICAL :: UnFoundFatal=.TRUE., ConvertWeertman
471
CHARACTER(LEN=MAX_NAME_LEN) :: USF_name, FlowSolverName, CoefName, WeertCoefName, WeertForm
472
473
SAVE :: normal, velo, DIM, SSA, FirstTime, FlowSolverName, UseFloatation
474
SAVE :: WeertCoefName, WeertExp, WeertForm, ConvertWeertman, BuddFrictionCoeff
475
476
477
USF_name = "Sliding_Budd"
478
479
BC => GetBC(Model % CurrentElement)
480
IF (.NOT.ASSOCIATED(BC))THEN
481
CALL Fatal(USF_name, 'No BC Found')
482
END IF
483
484
IF (FirstTime) THEN
485
FirstTime = .FALSE.
486
DIM = CoordinateSystemDimension()
487
IF ((DIM == 2).OR.(DIM == 3)) THEN
488
ALLOCATE(normal(DIM), velo(DIM))
489
ELSE
490
CALL FATAL(USF_name, 'Bad dimension of the problem')
491
END IF
492
493
ALLOCATE(BuddFrictionCoeff(Model % MaxElementNodes))
494
495
FlowSolverName = GetString( Model % Solver % Values , 'Flow Solver Name', GotIt )
496
IF (.NOT.Gotit) FlowSolverName = 'Flow Solution'
497
SELECT CASE (FlowSolverName)
498
CASE ('ssabasalflow')
499
SSA = .TRUE.
500
END SELECT
501
502
WeertCoefName = GetString( BC, 'Budd Conv Weertman coef name', GotIt )
503
IF (GotIt) THEN
504
ConvertWeertman = .TRUE.
505
WeertExp = GetConstReal( BC, 'Budd Conv Weertman exponent', GotIt )
506
IF (.NOT. GotIt) THEN
507
CALL FATAL(USF_name, 'Converting coef, need >Budd Conv Weertman exponent<')
508
END IF
509
WeertForm = GetString( BC, 'Budd Conv Weertman formulation', GotIt )
510
IF (.NOT. GotIt) THEN
511
CALL FATAL(USF_name, 'Converting coef, need >Budd Conv Weertman formulation<')
512
END IF
513
ELSE
514
ConvertWeertman = .FALSE.
515
END IF
516
517
END IF
518
519
!-----------------------------------------------------------------
520
! get some information upon active boundary element and its parent
521
!-----------------------------------------------------------------
522
BoundaryElement => Model % CurrentElement
523
elementNbNodes = GetElementNOFNodes(BoundaryElement)
524
525
! get number of node in element
526
DO elementNodeNumber=1,elementNbNodes
527
IF (BoundaryElement % NodeIndexes(elementNodeNumber) == nodenumber) EXIT
528
END DO
529
530
IF ( .NOT. ASSOCIATED(BoundaryElement) ) THEN
531
CALL FATAL(USF_Name,'No boundary element found')
532
END IF
533
other_body_id = BoundaryElement % BoundaryInfo % outbody
534
IF (other_body_id < 1) THEN ! only one body in calculation
535
ParentElement => BoundaryElement % BoundaryInfo % Right
536
IF ( .NOT. ASSOCIATED(ParentElement) ) ParentElement => BoundaryElement % BoundaryInfo % Left
537
ELSE ! we are dealing with a body-body boundary and assume that the normal is pointing outwards
538
ParentElement => BoundaryElement % BoundaryInfo % Right
539
IF (ParentElement % BodyId == other_body_id) ParentElement => BoundaryElement % BoundaryInfo % Left
540
END IF
541
! all the above was just so we can get the material properties of the parent element...
542
body_id = ParentElement % BodyId
543
material_id = ListGetInteger(Model % Bodies(body_id) % Values, 'Material', GotIt,UnFoundFatal = UnFoundFatal)
544
ParentMaterial => Model % Materials(material_id) % Values
545
IF (.NOT. ASSOCIATED(ParentMaterial)) THEN
546
WRITE(Message,'(A,I10,A,I10)')&
547
'No material values found for body no ', body_id,&
548
' under material id ', material_id
549
CALL FATAL(USF_Name,Message)
550
END IF
551
552
rhoi = GetConstReal( ParentMaterial, 'Density', GotIt )
553
IF (.NOT. GotIt) THEN
554
CALL FATAL(USF_Name, 'Material property Density not found.')
555
END IF
556
! rhoi = GetConstReal( BC, 'Budd Ice Density', GotIt )
557
! IF (.NOT.GotIt) THEN
558
! CALL FATAL(USF_name, 'Need Ice Density for the Budd sliding law')
559
! END IF
560
561
!C = GetConstReal( BC, 'Budd Friction Coefficient', GotIt )
562
563
BuddFrictionCoeff(1:elementNbNodes) = &
564
ListGetReal(BC, 'Budd Friction Coefficient', elementNbNodes, BoundaryElement % Nodeindexes, GotIt)
565
566
IF (.NOT. GotIt) THEN
567
CALL FATAL(USF_name, 'Need a Friction Coefficient for the Budd sliding law')
568
END IF
569
570
C = BuddFrictionCoeff(elementNodeNumber)
571
572
m = GetConstReal( BC, 'Budd Velocity Exponent', GotIt )
573
IF (.NOT. GotIt) THEN
574
CALL FATAL(USF_name, 'Need a velocity Exponent for the Budd sliding law')
575
END IF
576
577
q = GetConstReal( BC, 'Budd Zab Exponent', GotIt )
578
IF (.NOT. GotIt) THEN
579
CALL FATAL(USF_name, 'Need a Zab Exponent for the Budd sliding law')
580
END IF
581
582
Zab_offset = GetConstReal( BC, 'Budd Zab Offset', GotIt )
583
IF (.NOT. GotIt) THEN
584
Zab_offset = 0.0_dp
585
END IF
586
587
ut0 = GetConstReal( BC, 'Budd Linear Velocity', GotIt )
588
IF (.NOT. GotIt) THEN
589
CALL FATAL(USF_name, 'Need a Linear Velocity for the Budd sliding law')
590
END IF
591
592
g = GetConstReal( BC, 'Budd Gravity', GotIt )
593
IF (.NOT. GotIt) THEN
594
CALL FATAL(USF_name, 'Need Gravity for the Budd sliding law')
595
END IF
596
597
UseFloatation = GetLogical( BC, 'Budd Floatation', GotIt )
598
IF (.NOT. GotIt) THEN
599
CALL FATAL(USF_name, 'Need Floatation for the Budd sliding law')
600
END IF
601
602
H_scaling = GetLogical( BC, 'Budd Thickness Scaling', GotIt )
603
IF (.NOT. GotIt) THEN
604
H_scaling = .FALSE.
605
END IF
606
607
FlowVariable => VariableGet( Model % Variables, FlowSolverName,UnFoundFatal=UnFoundFatal)
608
FlowPerm => FlowVariable % Perm
609
FlowValues => FlowVariable % Values
610
611
IF (.NOT.SSA) THEN
612
NormalVar => VariableGet(Model % Variables,'Normal Vector',UnFoundFatal=UnFoundFatal)
613
NormalPerm => NormalVar % Perm
614
NormalValues => NormalVar % Values
615
616
DO i=1, DIM
617
normal(i) = -NormalValues(DIM*(NormalPerm(Nodenumber)-1) + i)
618
velo(i) = FlowValues( (DIM+1)*(FlowPerm(Nodenumber)-1) + i )
619
END DO
620
un = SUM(velo(1:DIM)*normal(1:DIM))
621
ut = SQRT( SUM( (velo(1:DIM)-un*normal(1:DIM))**2.0 ) )
622
ELSE
623
DO i=1, DIM-1
624
velo(i) = FlowValues( (DIM-1)*(FlowPerm(Nodenumber)-1) + i )
625
END DO
626
ut = SQRT(SUM( velo(1:DIM-1)**2.0 ))
627
END IF
628
629
! Zab is height above buoyancy of the upper free surface. This is
630
! calculated based on the effective pressure at the bed. The
631
! effective pressure at the bed is calculated as the normal stress
632
! at the lower boundary minus the External Pressure (which is set in
633
! the boundary condition section of the sif).
634
! Alternatively it can be approximated using the floatation condition.
635
IF (UseFloatation) THEN
636
637
Hvar => VariableGet( Model % Variables, "Depth",UnFoundFatal=UnFoundFatal)
638
HPerm => Hvar % Perm
639
HValues => Hvar % Values
640
H = HValues(HPerm(nodenumber))
641
642
rhow = GetConstReal( BC, 'Budd Ocean Density', GotIt )
643
IF (.NOT.GotIt) THEN
644
CALL FATAL(USF_name, 'Need Ocean Density for the Budd sliding law')
645
END IF
646
647
sl = GetCReal( ParentMaterial, 'Sea level', GotIt )
648
IF (.NOT.GotIt) THEN
649
CALL FATAL(USF_Name, 'Material property Sea level not found.')
650
END IF
651
652
! floatation condition
653
! (H - Zab) * rhoi = (sl - z) * rhow
654
! => Zab = H - (sl-z)*rhow/rhoi
655
IF (z .LT. sl) THEN
656
Zab = H - (sl-z)*rhow/rhoi
657
ELSE
658
Zab = H
659
END IF
660
661
IF (Zab .LT. 0.0) THEN
662
Zab = 0.0
663
END IF
664
665
! this "offset" to the height above buoyancy is intended to provide a non-zero
666
! basal drag due to contact with the bed, even when effective pressure is zero.
667
! Physically, this can be seen as a compromise between Elmer's "Weertman"
668
! implementation and Elmer's "Budd" implementation.
669
Zab = Zab + Zab_offset
670
671
ELSE
672
ep = effectivepressure (Model, nodenumber, z)
673
Zab = - ep / (g * rhoi)
674
END IF
675
676
ut = MAX(ut,ut0) ! linearize for very low velocities
677
678
IF (H_scaling) THEN
679
Zab = Zab / H
680
END IF
681
682
! Convert a Weertman sliding coefficient to a Budd sliding coefficient to
683
! give the same basal shear stress
684
IF (ConvertWeertman) THEN
685
WeertCoefVar => VariableGet( Model % Variables, WeertCoefName, UnFoundFatal=UnFoundFatal)
686
WeertCoefPerm => WeertCoefVar % Perm
687
WeertCoefValues => WeertCoefVar % Values
688
Cw = WeertCoefValues(WeertCoefPerm(Nodenumber))
689
690
SELECT CASE (WeertForm)
691
CASE ('power')
692
Cw = 10**Cw
693
CASE ('beta2')
694
Cw = Cw**2
695
CASE ('none')
696
CASE DEFAULT
697
CALL FATAL(USF_name, 'Unrecognised >Budd Conv Weertman formulation<')
698
END SELECT
699
700
IF ( (WeertExp.NE.1.0).OR.(m.NE.1.0) ) THEN
701
CALL FATAL(USF_name, 'Currently only works for velocity exponents = 1.0')
702
END IF
703
704
C = Cw / (Zab**q)
705
706
END IF
707
708
Bdrag = C * ut**(m-1.0) * Zab**q
709
710
CONTAINS
711
712
! Effective Pressure is overburden pressure (or, in our case, normal
713
! stress is more accurate) minus basal water pressure (or "external
714
! pressure").
715
!
716
! Pre-requisites:
717
! "External Pressure" needs to be defined in the relevant boundary
718
! condition.
719
! The "ComputeNormal" and "ComputeDevStressNS" solvers need to be
720
! active.
721
FUNCTION EffectivePressure (Model, nodenumber, y) RESULT(ep)
722
723
USE types
724
USE CoordinateSystems
725
USE SolverUtils
726
USE ElementDescription
727
USE DefUtils
728
IMPLICIT NONE
729
730
TYPE(Model_t) :: Model
731
REAL (KIND=dp) :: y , x
732
INTEGER :: nodenumber
733
734
REAL (KIND=dp) :: ep
735
736
TYPE(ValueList_t), POINTER :: BC, Material
737
TYPE(Variable_t), POINTER :: TimeVar, StressVariable, NormalVar, FlowVariable
738
TYPE(Element_t), POINTER :: BoundaryElement, ParentElement
739
REAL (KIND=dp), POINTER :: StressValues(:), NormalValues(:), FlowValues(:)
740
INTEGER, POINTER :: StressPerm(:), NormalPerm(:), FlowPerm(:)
741
INTEGER :: DIM, i, j, n, other_body_id, Ind(3,3)
742
REAL (KIND=dp) :: Pext
743
REAL (KIND=dp) :: Snn, ut, un, t
744
LOGICAL :: GotIt, FirstTime = .TRUE., Cauchy
745
REAL (KIND=dp), ALLOCATABLE :: Sig(:,:), normal(:), velo(:), Sn(:), AuxReal(:)
746
CHARACTER(LEN=MAX_NAME_LEN) :: USF_name
747
748
SAVE :: Sig, normal, velo, DIM, Ind, Sn, FirstTime
749
750
USF_name = "EffectivePressure"
751
752
IF (FirstTime) THEN
753
FirstTime = .FALSE.
754
DIM = CoordinateSystemDimension()
755
IF ((DIM == 2).OR.(DIM == 3)) THEN
756
ALLOCATE(Sig(DIM,DIM),normal(DIM),Sn(DIM))
757
ELSE
758
CALL FATAL(USF_name, 'Bad dimension of the problem')
759
END IF
760
DO i=1, 3
761
Ind(i,i) = i
762
END DO
763
Ind(1,2) = 4
764
Ind(2,1) = 4
765
Ind(2,3) = 5
766
Ind(3,2) = 5
767
Ind(3,1) = 6
768
Ind(1,3) = 6
769
END IF
770
771
! Check we have a boundary condition...
772
BoundaryElement => Model % CurrentElement
773
BC => GetBC(BoundaryElement)
774
IF (.NOT.ASSOCIATED(BC))THEN
775
CALL Fatal(USF_name, 'No BC Found')
776
END IF
777
778
n = GetElementNOFNodes()
779
ALLOCATE (auxReal(n))
780
781
! Get the external (probably water) pressure
782
! Use the convention Pext > 0 => Compression
783
auxReal(1:n) = GetReal( BC, 'External Pressure', GotIt )
784
DO i=1, n
785
IF (NodeNumber== BoundaryElement % NodeIndexes( i )) EXIT
786
END DO
787
Pext = auxReal(i)
788
DEALLOCATE(auxReal)
789
790
! Get the variable to compute the normal
791
NormalVar => VariableGet(Model % Variables,'Normal Vector',UnFoundFatal=UnFoundFatal)
792
NormalPerm => NormalVar % Perm
793
NormalValues => NormalVar % Values
794
795
! Get the stress variable
796
StressVariable => VariableGet( Model % Variables, 'Stress',UnFoundFatal=UnFoundFatal)
797
StressPerm => StressVariable % Perm
798
StressValues => StressVariable % Values
799
800
! Cauchy or deviatoric stresses ?
801
! First, get parent element
802
other_body_id = BoundaryElement % BoundaryInfo % outbody
803
IF (other_body_id < 1) THEN ! only one body in calculation
804
ParentElement => BoundaryElement % BoundaryInfo % Right
805
IF ( .NOT. ASSOCIATED(ParentElement) ) ParentElement => BoundaryElement % BoundaryInfo % Left
806
ELSE ! we are dealing with a body-body boundary and assume that the normal is pointing outwards
807
ParentElement => BoundaryElement % BoundaryInfo % Right
808
IF (ParentElement % BodyId == other_body_id) ParentElement => BoundaryElement % BoundaryInfo % Left
809
END IF
810
Material => GetMaterial(ParentElement)
811
Cauchy = ListGetLogical( Material , 'Cauchy', Gotit )
812
813
! stress tensor
814
DO i=1, DIM
815
DO j= 1, DIM
816
Sig(i,j) = &
817
StressValues( 2*DIM *(StressPerm(Nodenumber)-1) + Ind(i,j) )
818
END DO
819
IF (.NOT.Cauchy) THEN
820
Sig(i,i) = Sig(i,i) - FlowValues((DIM+1)*FlowPerm(Nodenumber))
821
END IF
822
END DO
823
824
! normal stress
825
DO i=1, DIM
826
normal(i) = -NormalValues(DIM*(NormalPerm(Nodenumber)-1) + i)
827
END DO
828
DO i=1, DIM
829
Sn(i) = SUM(Sig(i,1:DIM)*normal(1:DIM))
830
END DO
831
Snn = SUM( Sn(1:DIM) * normal(1:DIM) )
832
833
! effective pressure
834
ep = -Snn -Pext
835
836
END FUNCTION EffectivePressure
837
838
END FUNCTION Sliding_Budd
839
840
841
! ******************************************************************************
842
! *
843
! * Authors: Rupert Gladstone, Fabien Gillet-Chaulet
844
! * Email: [email protected]
845
! * Web:
846
! *
847
! * Original Date:
848
! * 2016/12/06
849
! *****************************************************************************
850
!> USF_Sliding.f90, function FreeSlipShelves
851
!>
852
!> Sets the basal drag to zero according to a grounded mask. Intended for use
853
!> when applying inverse methods in the presence of floating ice shelves.
854
!>
855
!> For the .sif (bottom boundary):
856
!> Slip Coefficient 2 = Variable beta
857
!> Real Procedure "ElmerIceUSF" "FreeSlipShelves"
858
!> Slip Coefficient 3 = Variable beta
859
!> Real Procedure "ElmerIceUSF" "FreeSlipShelves"
860
!> FreeSlipShelves mask name = Name of mask variable to use to set slip coef
861
!> to zero (default is GroundedMask)
862
!> FreeSlipShelves beta formulation = Power or Beta2 (same meaning as
863
!> described in DJDBeta_Adjoint solver)
864
!>
865
FUNCTION FreeSlipShelves (Model, nodenumber, BetaIn) RESULT(BetaOut)
866
867
USE DefUtils
868
869
IMPLICIT NONE
870
871
TYPE(Model_t) :: Model
872
REAL (KIND=dp) :: BetaIn
873
INTEGER :: nodenumber
874
875
REAL (KIND=dp) :: BetaOut, mask
876
LOGICAL :: FirstTime = .TRUE., GotIt
877
878
CHARACTER(LEN=MAX_NAME_LEN) :: FunctionName = 'FreeSlipShelves', BetaForm, MaskName
879
TYPE(ValueList_t), POINTER :: BC => NULL()
880
TYPE(Variable_t), POINTER :: PointerToMask => NULL()
881
REAL(KIND=dp), POINTER :: MaskValues(:) => NULL()
882
INTEGER, POINTER :: MaskPerm(:) => NULL()
883
884
SAVE FirstTime, MaskName, BetaForm
885
886
IF (FirstTime) THEN
887
888
BC => GetBC(Model % CurrentElement)
889
IF (.NOT.ASSOCIATED(BC))THEN
890
CALL Fatal(FunctionName, 'No BC Found')
891
END IF
892
893
MaskName = GetString( BC, 'FreeSlipShelves mask name', GotIt)
894
IF (.Not.GotIt) THEN
895
CALL WARN(FunctionName,'Keyword >FreeSlipShelves mask name< not found in boundary condition')
896
CALL WARN(FunctionName,'Taking default value >GroundedMask<')
897
WRITE(MaskName,'(A)') 'GroundedMask'
898
END IF
899
900
BetaForm = GetString( BC, 'FreeSlipShelves beta formulation', GotIt)
901
IF (.NOT.GotIt) THEN
902
WRITE(Message,'(A)') 'Need >FreeSlipShelves beta formulation< (e.g. Power or Beta2)'
903
CALL FATAL(FunctionName,Message)
904
END IF
905
906
FirstTime = .FALSE.
907
NULLIFY(BC)
908
END IF
909
910
! Obtain the value of the mask variable at the current node.
911
PointerToMask => VariableGet( Model % Variables, MaskName, UnFoundFatal=.TRUE.)
912
MaskValues => PointerToMask % Values
913
MaskPerm => PointerToMask % Perm
914
mask = MaskValues(MaskPerm(nodenumber))
915
NULLIFY(PointerToMask)
916
NULLIFY(MaskValues)
917
NULLIFY(MaskPerm)
918
919
! We assume mask value is zero or higher for grounded ice, and strictly below zero
920
! for floating ice.
921
IF (mask.LT.0.0_dp) THEN
922
BetaOut = 0.0_dp
923
ELSE
924
SELECT CASE (BetaForm)
925
CASE("Power","power")
926
BetaOut = 10.0_dp**BetaIn
927
CASE("Beta2","beta2")
928
BetaOut = BetaIn*BetaIn
929
CASE DEFAULT
930
WRITE(Message,'(A)') 'beta formulation not recognised'
931
CALL FATAL(FunctionName,Message)
932
END SELECT
933
END IF
934
935
END FUNCTION FreeSlipShelves
936
937