Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/Flotation.F90
5247 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: F. GILLET-CHAULET
26
! * Email: [email protected]
27
! * Web: http://elmerice.elmerfem.org
28
! *
29
! * Original Date: Nov. 2017
30
! *
31
! *****************************************************************************
32
!!! Apply the flotation criterion to update Zb and Zs from the ice thickness H
33
!!! Execute this solver on the bottom boundary where the thickness equation is solved
34
!!! IF the mesh is vertically extruded export Zs on the top surface.
35
!
36
! OUTPUT Variables:
37
! Zb
38
! Zs
39
! DZbDt (optional, if variable found and transient simulation)
40
! DZsDt (optional, if variable found and transient simulation)
41
!
42
! INPUT Variable:
43
! H
44
! bedrock (optional)
45
!
46
! PARAMETERS:
47
! Constants:
48
! zsea
49
! rhow
50
! Material:
51
! SSA Mean Density
52
!
53
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
54
SUBROUTINE Flotation_init( Model,Solver,dt,TransientSimulation )
55
USE DefUtils
56
IMPLICIT NONE
57
!------------------------------------------------------------------------------
58
TYPE(Solver_t), TARGET :: Solver
59
TYPE(Model_t) :: Model
60
REAL(KIND=dp) :: dt
61
LOGICAL :: TransientSimulation
62
!--------------------------------------------------------------------------
63
CHARACTER(LEN=MAX_NAME_LEN) :: ZbName,ZsName,HName
64
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName='Flotation'
65
TYPE(ValueList_t), POINTER :: SolverParams
66
LOGICAL :: GotIt
67
68
SolverParams => Solver % Values
69
70
ZbName = GetString(SolverParams, 'Bottom Surface Name', GotIt)
71
IF (.NOT.GotIt) THEN
72
CALL INFO(SolverName, 'Bottom Surface Name not found - using default Zb', level=3)
73
CALL ListAddString(SolverParams,'Bottom Surface Name','Zb')
74
END IF
75
76
ZsName = GetString(SolverParams, 'Top Surface Name', GotIt)
77
IF (.NOT.GotIt) THEN
78
CALL INFO(SolverName, 'Top Surface Name not found - using default Zs', level=3)
79
CALL ListAddString(SolverParams,'Top Surface Name','Zs')
80
END IF
81
82
HName = GetString(SolverParams, 'Thickness Variable Name', GotIt)
83
IF (.NOT.GotIt) THEN
84
CALL INFO(SolverName, 'Thickness Variable Name not found - using default H', level=3)
85
CALL ListAddString(SolverParams,'Thickness Variable Name','H')
86
END IF
87
88
END SUBROUTINE Flotation_init
89
!------------------------------------------------------------------------------
90
!------------------------------------------------------------------------------
91
SUBROUTINE Flotation( Model,Solver,dt,Transient )
92
!------------------------------------------------------------------------------
93
USE CoordinateSystems
94
USE MeshUtils
95
USE DefUtils
96
97
IMPLICIT NONE
98
!------------------------------------------------------------------------------
99
TYPE(Model_t) :: Model
100
TYPE(Solver_t), TARGET :: Solver
101
LOGICAL :: Transient
102
REAL(KIND=dp) :: dt
103
!------------------------------------------------------------------------------
104
! Local variables
105
!------------------------------------------------------------------------------
106
TYPE(Mesh_t),POINTER :: Mesh
107
TYPE(Solver_t),POINTER :: PSolver
108
TYPE(Variable_t),POINTER :: Var
109
TYPE(Variable_t),POINTER :: ZbVar,ZsVar
110
TYPE(Variable_t),POINTER :: HVar,BedVar
111
TYPE(Variable_t),POINTER :: GLMask,HafVar
112
TYPE(Variable_t),POINTER :: sftgif,sftgrf,sftflf
113
TYPE(Element_t), POINTER :: Element
114
TYPE(ValueList_t),POINTER :: BodyForce,Material, Params
115
TYPE(Nodes_t),SAVE :: ElementNodes
116
TYPE(GaussIntegrationPoints_t) :: IP
117
118
REAL(KIND=dp),DIMENSION(:),ALLOCATABLE,SAVE :: Density
119
REAL(KIND=dp),DIMENSION(:),ALLOCATABLE,SAVE :: GL
120
REAL(KIND=dp),DIMENSION(:),ALLOCATABLE,SAVE :: MinH,NodalH
121
REAL(KIND=dp),ALLOCATABLE,SAVE :: Basis(:)
122
REAL(KIND=dp) :: zsea,rhow,rhoi
123
REAL(KIND=dp) :: H,zb,zs,bedrock,Hf
124
REAL(KIND=dp), PARAMETER :: EPS=EPSILON(1.0)
125
REAL(KIND=dp) :: FillValue
126
REAL(KIND=dp) :: flarea,grarea,area,IParea,detJ
127
128
129
INTEGER,DIMENSION(:),POINTER,SAVE :: BotPointer,TopPointer,UpPointer
130
INTEGER, POINTER,SAVE :: NodeIndexes(:)
131
INTEGER :: GroundedNode
132
INTEGER :: ActiveDirection
133
INTEGER :: t,i,n,kk,ll
134
INTEGER :: topnode
135
INTEGER :: Active
136
INTEGER :: Eindex
137
INTEGER :: GlnIP
138
139
LOGICAL,SAVE :: Initialized = .FALSE.
140
LOGICAL,SAVE :: ExtrudedMesh=.False.
141
LOGICAL :: Found,GotIt
142
LOGICAL :: BoundarySolver
143
LOGICAL :: ComputeIceMasks,LimitedSolution,IceFree
144
LOGICAL :: stat
145
LOGICAL :: SEP
146
147
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName='Flotation'
148
CHARACTER(LEN=MAX_NAME_LEN) :: ZbName,ZsName,HName
149
150
!------------------------------------------------------------------------------
151
152
Mesh => Model % Mesh
153
154
Params => Solver % Values
155
156
BoundarySolver = ( Solver % ActiveElements(1) > Model % Mesh % NumberOfBulkElements )
157
158
!!! get required variables Zb,Zs,H
159
ZbName = ListGetString(Params, 'Bottom Surface Name', UnFoundFatal=.TRUE.)
160
zbVar => VariableGet( Model % Mesh % Variables, ZbName,UnFoundFatal=.TRUE.)
161
162
ZsName = ListGetString(Params, 'Top Surface Name', UnFoundFatal=.TRUE.)
163
zsVar => VariableGet( Model % Mesh % Variables, ZsName,UnFoundFatal=.TRUE.)
164
165
HName = ListGetString(Params, 'Thickness Variable Name', UnFoundFatal=.TRUE.)
166
HVar => VariableGet( Model % Mesh % Variables, HName, UnFoundFatal=.TRUE.)
167
168
!!
169
!! get optional variables GLMAsk,bedrock
170
GLMAsk => VariableGet( Model % Mesh % Variables, 'GroundedMask')
171
IF (.NOT.ASSOCIATED(GLMAsk)) THEN
172
Message='GroundedMask not found'
173
CALL INFO(SolverName,Message,level=5)
174
ELSE
175
IF ((ParEnv % PEs>1).AND.(.NOT.ASSOCIATED(Solver%Matrix))) &
176
CALL FATAL(SolverName,'Solver%Matrix should be associated to update GLMask')
177
END IF
178
BedVar => VariableGet( Model % Mesh % Variables, 'bedrock')
179
IF (.NOT.ASSOCIATED(BedVar)) THEN
180
Message='bedrock not found'
181
CALL INFO(SolverName,Message,level=5)
182
END IF
183
! height above flotation
184
HafVar => VariableGet( Model % Mesh % Variables, 'Haf')
185
IF (.NOT.ASSOCIATED(HafVar)) THEN
186
Message='<Haf> not found; do not compute height above flotation'
187
CALL INFO(SolverName,Message,level=5)
188
END IF
189
190
!! compute ice area farctions
191
ComputeIceMasks = ListGetLogical(Params,"compute ice area fractions",Gotit)
192
LimitedSolution = .FALSE.
193
IF (ComputeIceMasks) THEN
194
FillValue = ListGetConstReal(Params,"Ice free mask values",Gotit)
195
IF (.NOT.Gotit) FillValue=0._dp
196
197
sftgif => VariableGet( Model % Mesh % Variables, 'sftgif',UnFoundFatal=.TRUE.)
198
sftgif % Values = 0._dp
199
IF (sftgif % TYPE /= Variable_on_elements) &
200
CALL FATAL(SolverName,"sftgif type should be on_elements")
201
sftgrf => VariableGet( Model % Mesh % Variables, 'sftgrf',UnFoundFatal=.TRUE.)
202
sftgrf % Values = 0._dp
203
IF (sftgrf % TYPE /= Variable_on_elements) &
204
CALL FATAL(SolverName,"sftgrf type should be on_elements")
205
sftflf => VariableGet( Model % Mesh % Variables, 'sftflf',UnFoundFatal=.TRUE.)
206
sftflf % Values = 0._dp
207
IF (sftflf % TYPE /= Variable_on_elements) &
208
CALL FATAL(SolverName,"sftflf type should be on_elements")
209
210
! change number of IPs for partially grounded elements
211
GLnIP=ListGetInteger( Params,'GL integration points number',SEP)
212
213
! check if we have a limited solution
214
! internal Elmer limiters...
215
LimitedSolution=ListCheckPresentAnyBodyForce(CurrentModel, TRIM(HName)//" Lower Limit")
216
IF (.NOT.LimitedSolution) &
217
LimitedSolution=ListCheckPresentAnyMaterial(CurrentModel, "Min "//TRIM(HName))
218
ENDIF
219
220
!!! Do some initialisation/allocation
221
IF ((.NOT.Initialized) .OR. Mesh % Changed) THEN
222
223
ActiveDirection = ListGetInteger(Params,'Active Coordinate',ExtrudedMesh)
224
IF (ExtrudedMesh) THEN
225
! Choose active direction coordinate and set corresponding unit vector
226
!---------------------------------------------------------------------
227
228
PSolver => Solver
229
CALL DetectExtrudedStructure( Mesh, PSolver, ExtVar = Var, BotNodePointer = BotPointer , &
230
TopNodePointer = TopPointer, UpNodePointer = UpPointer)
231
END IF
232
233
IF (Initialized) deallocate(Density,GL,MinH,NodalH,Basis)
234
235
N=Model % MaxElementNodes
236
allocate(Density(N),GL(N),MinH(N),NodalH(N),Basis(N))
237
238
Initialized = .TRUE.
239
END IF
240
!!
241
242
zsea = ListGetCReal( Model % Constants, 'Sea Level', UnFoundFatal=.TRUE. )
243
rhow = ListGetCReal( Model % Constants, 'water density', UnFoundFatal=.TRUE. )
244
245
IF (ASSOCIATED(GLMask)) GLMask%Values = -1.0
246
247
IF (BoundarySolver) THEN
248
Active = GetNOFBoundaryElements()
249
ELSE
250
Active = Solver % Mesh % NumberOfBulkElements
251
ENDIF
252
253
IF (ASSOCIATED(HafVar)) HafVar%Values = 0._dp
254
255
Do t=1,Active
256
257
IF (BoundarySolver) THEN
258
Element => GetBoundaryElement(t,Solver)
259
ELSE
260
Element => Solver % Mesh % Elements(t)
261
CurrentModel % CurrentElement => Element
262
ENDIF
263
264
Eindex = Element%ElementIndex
265
n = GetElementNOFNodes(Element)
266
NodeIndexes => Element % NodeIndexes
267
268
Material => GetMaterial(Element)
269
BodyForce => GetBodyForce(Element)
270
271
NodalH(1:n) = HVar%Values(HVar%Perm(NodeIndexes(1:n)))
272
273
IF (ComputeIceMasks) THEN
274
kk=sftgif % Perm(Eindex)
275
IF (kk>0) sftgif % Values ( kk ) = 1._dp
276
END IF
277
278
! If H is limited check if all element is at lower limit...
279
IceFree=.FALSE.
280
IF (LimitedSolution) THEN
281
MinH = 0._dp
282
! check for limited solution;
283
MinH = ListGetConstReal(BodyForce,TRIM(HName)//' Lower Limit', Gotit)
284
IF (.NOT.Gotit) &
285
MinH = ListGetConstReal(Material,'Min '//TRIM(HName), Gotit)
286
IF (.NOT.GotIt) CALL FATAL(SolverName,TRIM(HName)//" not found...but was supposed to be limited")
287
IF (ALL((NodalH(1:n)-MinH(1:n)) <= EPS)) IceFree=.TRUE.
288
END IF
289
290
Density(1:n) = ListGetReal( Material, 'SSA Mean Density',n, NodeIndexes,UnFoundFatal=.TRUE.)
291
292
GroundedNode=0
293
GL=-1
294
Do i=1,n
295
296
H=NodalH(i)
297
rhoi=Density(i)
298
zb=zsea-H*rhoi/rhow
299
! if bedrock defined check flotation criterion
300
IF(ASSOCIATED(BedVar)) THEN
301
bedrock=BedVar%Values(BedVar%Perm(NodeIndexes(i)))
302
IF (zb <= bedrock) THEN
303
zb=bedrock
304
GL(i)=1
305
GroundedNode=GroundedNode+1
306
END IF
307
IF (ASSOCIATED(HafVar)) THEN
308
Hf=MAX(zsea-bedrock,0._dp)*rhow/rhoi
309
HafVar%Values(HafVar%Perm(NodeIndexes(i)))=H-Hf
310
END IF
311
END IF
312
313
zs=zb+H
314
ZbVar%Values(ZbVar%Perm(NodeIndexes(i)))=zb
315
ZsVar%Values(ZsVar%Perm(NodeIndexes(i)))=zs
316
317
! Export Zs on top surface if required
318
IF (ExtrudedMesh) THEN
319
topnode=TopPointer(NodeIndexes(i))
320
ZsVar%Values(ZsVar%Perm(topnode))=zs
321
END IF
322
323
End do
324
IF (ASSOCIATED(GLMask)) THEN
325
IF ((GroundedNode > 0).AND.(GroundedNode < n)) THEN
326
WHERE(GL > 0._dp) GL=0._dp
327
END IF
328
GLMask%Values(GLMask%Perm(NodeIndexes(1:n)))= GL(1:n) * ABS(GLMask%Values(GLMask%Perm(NodeIndexes(1:n))))
329
END IF
330
331
332
IF (ComputeIceMasks) THEN
333
IF (GroundedNode == 0) THEN
334
!floating element
335
IF (sftgrf % Perm(Eindex) > 0 ) &
336
sftgrf % Values ( sftgrf % Perm(Eindex)) = 0._dp
337
IF (sftflf % Perm(Eindex) > 0 ) &
338
sftflf % Values ( sftflf % Perm(Eindex)) = 1._dp
339
ELSEIF (GroundedNode < n) THEN
340
!partly grounded
341
CALL GetElementNodes( ElementNodes, Element )
342
IF (SEP .AND. GLnIP > 0 ) THEN
343
IP = GaussPoints( Element ,np=GLnIP )
344
ELSE
345
IP = GaussPoints( Element )
346
ENDIF
347
area=0._dp
348
flarea=0._dp
349
grarea=0._dp
350
DO ll=1,IP % n
351
stat = ElementInfo( Element, ElementNodes, IP % U(ll), IP % V(ll), &
352
IP % W(ll), detJ, Basis )
353
rhoi=SUM(Density(1:n)*Basis(1:n))
354
H=SUM(NodalH(1:n)*Basis(1:n))
355
bedrock=SUM(BedVar%Values(BedVar%Perm(NodeIndexes(1:n)))*Basis(1:n))
356
Hf=(zsea-bedrock)*rhow/rhoi
357
IParea=detJ*IP % s(ll)
358
IF (H < Hf) THEN
359
flarea=flarea+IParea
360
ELSE
361
grarea=grarea+IParea
362
ENDIF
363
area=area+IParea
364
END DO
365
366
IF (sftgrf % Perm(Eindex) > 0 ) &
367
sftgrf % Values ( sftgrf % Perm(Eindex)) = grarea/area
368
IF (sftflf % Perm(Eindex) > 0 ) &
369
sftflf % Values ( sftflf % Perm(Eindex)) = flarea/area
370
ELSE
371
!grounded
372
IF (sftgrf % Perm(Eindex) > 0 ) &
373
sftgrf % Values ( sftgrf % Perm(Eindex)) = 1._dp
374
IF (sftflf % Perm(Eindex) > 0 ) &
375
sftflf % Values ( sftflf % Perm(Eindex)) = 0._dp
376
END IF
377
IF (IceFree) THEN
378
IF (sftgif % Perm(Eindex) > 0) &
379
sftgif % Values ( sftgif % Perm(Eindex)) = FillValue
380
IF (sftgrf % Perm(Eindex) > 0) &
381
sftgrf % Values ( sftgrf % Perm(Eindex)) = FillValue
382
IF (sftflf % Perm(Eindex) > 0) &
383
sftflf % Values ( sftflf % Perm(Eindex)) = FillValue
384
END IF
385
ENDIF
386
End Do
387
388
IF (ASSOCIATED(GLMask).AND.( ParEnv % PEs>1 )) CALL ParallelSumVector( Solver % Matrix, GLMask%Values ,1 )
389
390
!------------------------------------------------------------------------------
391
END SUBROUTINE Flotation
392
!------------------------------------------------------------------------------
393
394