Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/UserFunctions/USF_Contact.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:
26
! * Email:
27
! * Web: http://elmerice.elmerfem.org
28
! *
29
! * Original Date:
30
! * Date Modifications:2007/10/25. Gael Durand
31
! *
32
! *****************************************************************************
33
!> tests if resting ice becomes floating ice (GroundedMask from 0 or 1 to -1)
34
!>
35
!> Return a friction coefficient
36
!> -from sliding weertman for resting ice (GroundedMask = 0 or 1)
37
!> -of 0 for floating ice (GroundedMask = -1)
38
!> 2014 : Introduce 3 different ways of defining the grounding line (Mask = 0)
39
!> Last Grounded ; First Floating ; Discontinuous
40
41
FUNCTION SlidCoef_Contact ( Model, nodenumber, y) RESULT(Bdrag)
42
43
USE ElementDescription
44
USE DefUtils
45
46
IMPLICIT NONE
47
48
TYPE(Model_t) :: Model
49
TYPE(Solver_t) :: Solver
50
TYPE(variable_t), POINTER :: TimeVar, NormalVar, VarSurfResidual, GroundedMaskVar, HydroVar, DistanceVar, FrictionVar
51
TYPE(ValueList_t), POINTER :: BC
52
TYPE(Element_t), POINTER :: Element, CurElement, BoundaryElement
53
TYPE(Nodes_t), SAVE :: Nodes
54
55
REAL(KIND=dp), POINTER :: NormalValues(:), ResidValues(:), GroundedMask(:), Hydro(:), &
56
Distance(:), FrictionValues(:)
57
REAL(KIND=dp) :: Bdrag, t, told, thresh, FrictionValue
58
REAL(KIND=dp), ALLOCATABLE :: Normal(:), Fwater(:), Fbase(:)
59
60
INTEGER, POINTER :: NormalPerm(:), ResidPerm(:), GroundedMaskPerm(:), HydroPerm(:), &
61
DistancePerm(:), FrictionPerm(:)
62
INTEGER :: nodenumber, ii, DIM, GL_retreat, n, tt, Nn, jj, MSum, ZSum
63
64
LOGICAL :: FirstTime = .TRUE., GotIt, Yeschange, GLmoves, Friction, UnFoundFatal=.TRUE.
65
66
REAL (KIND=dp) :: y, relChange, relChangeOld, Sliding_Budd, Sliding_Weertman, Friction_Coulomb
67
68
REAL(KIND=dp) :: comp, cond, TestContact
69
CHARACTER(LEN=MAX_NAME_LEN) :: USF_Name='SlidCoef_Contact', Sl_Law, GLtype, FrictionVarName
70
CHARACTER(LEN=MAX_NAME_LEN) :: FlowLoadsName, FlowSolutionName
71
72
SAVE FirstTime, yeschange, told, GLmoves, thresh, GLtype, TestContact
73
SAVE DIM, USF_Name, Normal, Fwater, Fbase, relChangeOld, Sl_Law
74
SAVE FrictionVar, FrictionValues, FrictionValue, FrictionPerm, BC, FlowLoadsName
75
SAVE FlowSolutionName
76
77
!----------------------------------------------------------------------------
78
79
! Real time import
80
Timevar => VariableGet( Model % Variables,'Time')
81
t = TimeVar % Values(1)
82
83
! GroundedMask import
84
GroundedMaskVar => VariableGet( Model % Mesh % Variables, 'GroundedMask',UnFoundFatal=UnFoundFatal)
85
GroundedMask => GroundedMaskVar % Values
86
GroundedMaskPerm => GroundedMaskVar % Perm
87
88
relchange = Model % Solver % Variable % NonLinChange
89
90
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
91
! First time step for the First time
92
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
93
94
IF (FirstTime) THEN
95
DIM = CoordinateSystemDimension()
96
FirstTime = .FALSE.
97
n = Model % MaxElementNodes
98
told = t
99
100
! means have the possibility to change
101
yesChange = .TRUE.
102
ALLOCATE( Normal(DIM), Fwater(DIM), Fbase(DIM) )
103
104
relChangeOld = relChange
105
106
! choice of the Sliding Law
107
BoundaryElement => Model % CurrentElement
108
BC => GetBC(BoundaryElement)
109
110
FlowSolutionName = GetString( BC, 'Flow Solution Name', GotIt )
111
IF (.NOT.Gotit) THEN
112
FlowSolutionName = 'Flow Solution'
113
CALL Info(USF_Name, 'Using default name >Flow Solution<', Level=4)
114
END IF
115
WRITE(FlowLoadsName,'(A)') TRIM(FlowSolutionName)//' Loads'
116
117
Sl_Law = GetString( BC, 'Sliding Law', GotIt )
118
IF (.NOT.Gotit) THEN
119
CALL FATAL(USF_Name,'No "Sliding law" Name given')
120
END IF
121
122
GLtype = GetString( BC, 'Grounding Line Definition', GotIt )
123
IF (.NOT.Gotit) THEN
124
GLtype = 'last grounded'
125
CALL Info(USF_Name, 'Grounded Line Defined as the last Grounded point', Level=3)
126
ELSE
127
WRITE(Message, '(A,A)') 'Grounding Line Defined as ', GLtype
128
CALL Info(USF_Name, Message, Level=3)
129
END IF
130
131
! Possibility to fix the grounding line, default is a moving Grounding Line
132
GLmoves = GetLogical( BC, 'Grounding line moves', GotIt )
133
IF (.NOT.GotIt) THEN
134
GLmoves = .TRUE.
135
END IF
136
IF (GLmoves) THEN
137
CALL Info(USF_Name, 'GL may move by default', Level=3)
138
CALL Info(USF_Name, 'If you want to fix the Grounding Line, put the keyword "Grounding line moves" to False', Level=3)
139
ELSE
140
CALL Info(USF_Name, 'GL will be fixed', Level=3)
141
END IF
142
143
TestContact = GetConstReal( BC, 'Test Contact Tolerance', GotIt )
144
IF (.NOT.Gotit) THEN
145
TestContact = 1.0e-3
146
CALL Info(USF_Name, 'Contact will be tested for a tolerance of 1.0e-3', Level=3)
147
ELSE
148
WRITE(Message, '(A,e14.8)') 'Contact tested for a tolerance of ', TestContact
149
CALL Info(USF_Name, Message, Level=3)
150
END IF
151
152
! Possibility to avoid detachement from nodes that are too far inland from the Grounding line
153
! Uses the DistanceSolver
154
! Default is non possible detachment
155
thresh = GetConstReal( BC, 'non detachment inland distance', GotIt )
156
IF (.NOT.GotIt) THEN
157
thresh = -10000.0_dp
158
CALL INFO( USF_Name, 'far inland nodes have the possibility to detach by default', Level=3)
159
CALL INFO( USF_Name, 'to avoid detachment (when bedrock is well below sea level),', Level=3)
160
CALL INFO( USF_Name, 'use the keyword "non detachment inland distance" to the distance you wish', Level=3)
161
CALL INFO( USF_Name, 'This works with the DistanceSolver', Level=3)
162
ELSE
163
CALL INFO( USF_Name, 'far inland nodes will not detach', level=3)
164
END IF
165
ENDIF
166
167
IF(Sl_Law(1:10) == 'prescribed') THEN
168
IF(Sl_Law(1:16) == 'prescribed value') THEN
169
FrictionValue = ListGetConstReal(BC, 'Friction Value', UnfoundFatal=.TRUE.)
170
ELSE
171
FrictionVarName = GetString( BC, 'Friction Variable Name', GotIt )
172
IF(.NOT. GotIt) CALL Fatal(USF_Name, 'Prescribed friction requested but no &
173
"Friction Variable Name" found!')
174
FrictionVar => VariableGet(Model % Mesh % Variables, FrictionVarName)
175
IF(ASSOCIATED(FrictionVar)) THEN
176
FrictionValues => FrictionVar % Values
177
FrictionPerm => FrictionVar % Perm
178
ELSE
179
WRITE(Message, '(A,A)') 'Unable to find variable: ',FrictionVarName
180
CALL Fatal(USF_Name, Message)
181
END IF
182
END IF
183
END IF
184
185
186
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
187
! First time step for a New time
188
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
189
190
IF ( t > told ) THEN
191
told = t
192
yesChange = .TRUE.
193
relChangeOld = relChange
194
END IF
195
196
! to use the non detachment possibility when a grounded node is too far from the grounding line
197
! and positioned on a well below sea level bedrock
198
IF (thresh.GT.0.0) THEN
199
DistanceVar => VariableGet( Model % Mesh % Variables, 'Distance',UnFoundFatal=UnFoundFatal)
200
Distance => DistanceVar % Values
201
DistancePerm => DistanceVar % Perm
202
END IF
203
204
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
205
! Look at the convergence of the FlowSolver.
206
! If relative change < TestContact, test if traction occurs. To apply one time
207
!
208
! Only to release contact between bed and ice as hydrostatic pressure is higher than normal stress
209
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
210
211
Normal = 0.0_dp
212
Fwater = 0.0_dp
213
Fbase = 0.0_dp
214
215
IF ( (relChange.NE.relChangeOld) .AND. (relchange.GT.0.0_dp) .AND. &
216
& (relchange.LT.TestContact) .AND. (yesChange) .AND. GLmoves ) THEN
217
! Change the basal condition just once per timestep
218
yesChange = .FALSE.
219
220
CALL Info(USF_name,'FLOW SOLVER HAS SLIGHTLY CONVERGED: look for new basal conditions', Level=3)
221
222
VarSurfResidual => VariableGet( Model % Mesh % Variables, FlowLoadsName, UnFoundFatal=UnFoundFatal)
223
ResidPerm => VarSurfResidual % Perm
224
ResidValues => VarSurfResidual % Values
225
226
NormalVar => VariableGet(Model % Variables,'Normal Vector',UnFoundFatal=UnFoundFatal)
227
NormalPerm => NormalVar % Perm
228
NormalValues => NormalVar % Values
229
230
!Force exerted by the water, computed for each good boundary nodes (whatever on the bed or floating)
231
!From GetHydrostaticLoads
232
233
HydroVar => VariableGet( Model % Mesh % Variables, 'Fw',UnFoundFatal=UnFoundFatal)
234
Hydro => HydroVar % Values
235
HydroPerm => HydroVar % Perm
236
237
! Retreat of the Grounding line if Hydro loads higher than residual values
238
GL_retreat = 0
239
240
CurElement => Model % CurrentElement
241
DO tt = 1, Model % NumberOfBoundaryElements
242
243
Element => GetBoundaryElement(tt)
244
IF (ParEnv % myPe .NE. Element % partIndex) CYCLE
245
n = GetElementNOFNodes(Element)
246
247
CALL GetElementNodes(Nodes, Element)
248
249
IF (ANY(GroundedMaskPerm(Element % NodeIndexes(1:n))==0)) CYCLE
250
DO ii = 1,n
251
252
Nn = GroundedMaskPerm(Element % NodeIndexes(ii))
253
! the grounded mask is not defined here
254
IF (Nn==0) CYCLE
255
IF (GroundedMask(Nn) < -0.5_dp) CYCLE
256
257
jj = Element % NodeIndexes(ii)
258
259
! comparison between water load and reaction
260
261
Normal = NormalValues(DIM*(NormalPerm(jj)-1)+1 : DIM*NormalPerm(jj))
262
Fwater = Hydro(DIM*(HydroPerm(jj)-1)+1 : DIM*HydroPerm(jj))
263
Fbase = ResidValues((DIM+1)*(ResidPerm(jj)-1)+1 : (DIM+1)*ResidPerm(jj)-1)
264
265
! comparison between water pressure and bed action
266
comp = SUM( Fwater * Normal ) + SUM( Fbase * Normal )
267
268
IF (comp .GE. 0.0_dp) THEN
269
IF (thresh.LE.0.0_dp) THEN
270
GroundedMask(Nn) = -1.0_dp
271
GL_retreat = GL_retreat + 1
272
WRITE(Message,*)'Retreat of the Grounding Line : ', Nodes % x(ii), Nodes % y(ii)
273
CALL INFO(USF_Name, Message, Level=4)
274
ELSE
275
IF ( Distance(DistancePerm(Element % NodeIndexes(ii))).LE.thresh ) THEN
276
GroundedMask(Nn) = -1.0_dp
277
GL_retreat = GL_retreat + 1
278
WRITE(message,*)'Retreat of the Grounding Line : ', Nodes % x(ii), Nodes % y(ii)
279
CALL INFO(USF_Name, Message, Level=4)
280
END IF
281
END IF
282
END IF
283
END DO
284
285
END DO
286
Model % CurrentElement => CurElement
287
288
! with the previous step
289
! Some 0 (Grounding line) may have been replaced by -1 (floating nodes)
290
! here replacement of some 1 by 0's
291
292
IF (GL_retreat.GT.0) THEN
293
CurElement => Model % CurrentElement
294
DO tt = 1, Model % NumberOfBoundaryElements
295
296
Element => GetBoundaryElement(tt)
297
IF (ParEnv % myPe .NE. Element % partIndex) CYCLE
298
n = GetElementNOFNodes(Element)
299
300
CALL GetElementNodes(Nodes, Element)
301
MSum = 0
302
ZSum = 0
303
304
IF (ANY(GroundedMaskPerm(Element % NodeIndexes(1:n))==0)) CYCLE
305
DO ii = 1,n
306
307
Nn = GroundedMaskPerm(Element % NodeIndexes(ii))
308
! the grounded mask is not defined here
309
IF (Nn==0) CYCLE
310
MSum = MSum + INT(GroundedMask(Nn))
311
IF (GroundedMask(Nn)==0.0_dp) ZSum = ZSum + 1
312
313
END DO
314
315
IF (MSum+ZSum .LT. n) THEN
316
DO ii=1,n
317
Nn = GroundedMaskPerm(Element % NodeIndexes(ii))
318
IF (Nn==0) CYCLE
319
320
IF (GroundedMask(Nn)==1.0_dp) THEN
321
GroundedMask(Nn)=0.0_dp
322
END IF
323
324
END DO
325
END IF
326
327
END DO
328
Model % CurrentElement => CurElement
329
END IF
330
END IF
331
332
relChangeOld = relChange
333
334
335
IF (GroundedMaskPerm(nodenumber) > 0) THEN
336
! for the bottom surface, where the GroundedMask is defined
337
cond = GroundedMask(GroundedMaskPerm(nodenumber))
338
339
! Definition of the Grounding line in term of friction
340
! If GLtype = Last Grounded -> Bdrag = 0 if Nodal Mask < 0
341
! If GLtype = First Floating -> Bdrag = 0 if Nodal Mask <=0
342
! If GLtype = Discontinuous -> Bdrag = 0 if at one node of the element Mask<=0
343
344
Friction = .FALSE.
345
SELECT CASE(GLtype)
346
CASE('last grounded')
347
IF (cond > -0.5) Friction = .TRUE.
348
CASE('first floating')
349
IF (cond > 0.5) Friction = .TRUE.
350
CASE('discontinuous')
351
BoundaryElement => Model % CurrentElement
352
IF (ALL(GroundedMask(GroundedMaskPerm(BoundaryElement % NodeIndexes))>-0.5)) Friction = .TRUE.
353
CASE DEFAULT
354
WRITE(Message, '(A,A)') 'GL type not recognised ', GLtype
355
CALL FATAL( USF_Name, Message)
356
END SELECT
357
358
IF (Friction) THEN
359
! grounded node
360
SELECT CASE(Sl_law)
361
CASE ('weertman')
362
Bdrag = Sliding_weertman(Model, nodenumber, y)
363
CASE ('budd')
364
Bdrag = Sliding_Budd(Model, nodenumber, y)
365
CASE ('coulomb')
366
Bdrag = Friction_Coulomb(Model, nodenumber, y)
367
CASE('prescribed beta2')
368
Bdrag = FrictionValues(FrictionPerm(nodenumber))**2.0_dp
369
CASE('prescribed power')
370
Bdrag = 10.0_dp**FrictionValues(FrictionPerm(nodenumber))
371
CASE('prescribed variable')
372
Bdrag = FrictionValues(FrictionPerm(nodenumber))
373
CASE('prescribed value')
374
Bdrag = FrictionValue
375
CASE DEFAULT
376
WRITE(Message, '(A,A)') 'Sliding law not recognised ',Sl_law
377
CALL FATAL( USF_Name, Message)
378
END SELECT
379
ELSE
380
! floating node
381
Bdrag = 0.0_dp
382
END IF
383
ELSE
384
! for other surfaces, typically for lateral surfaces within buttressing experiments
385
Bdrag = Sliding_weertman(Model, nodenumber, y)
386
END IF
387
END FUNCTION SlidCoef_Contact
388
389
390
391
392