Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/UserFunctions/Buoyancy.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
! * Date Modifications:
31
! * 2009/03/17 GAG generalised for 3D problems and non-linear elements
32
! *****************************************************************************
33
!>
34
!>
35
!>
36
!>
37
! *****************************************************************************
38
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
39
!>
40
!> Buoyancy user functions
41
!>
42
!> SeaPressure returns the pressure -rho_w. g . (Hsl - S - b.Ns.dt)
43
!> where Ns = sqrt(1 + (dS/dx)^2 + (dS/dy)^2)
44
!> b = melting below the shelf (normal flux)
45
!> External Pressure = ....
46
!>
47
!> SeaSpring returns the viscous spring rho_w.g.Ns.dt
48
!> Normal-Tangential set to true
49
!> Slip Coefficient 1 = ....
50
!>
51
!> Adapted from SeaPressureOld. Allows accretion melting below the shelf.
52
!> 2009/03/17 GAG
53
!> - generalised for 3D problems and non-linear elements
54
FUNCTION SeaPressure ( Model, nodenumber, y) RESULT(pw)
55
USE types
56
USE CoordinateSystems
57
USE SolverUtils
58
USE ElementDescription
59
USE DefUtils
60
IMPLICIT NONE
61
TYPE(Model_t) :: Model
62
TYPE(Solver_t):: Solver
63
TYPE(Nodes_t), SAVE :: Nodes
64
TYPE(variable_t), POINTER :: Timevar
65
TYPE(Element_t), POINTER :: BoundaryElement, BCElement, CurElement, ParentElement
66
TYPE(ValueList_t), POINTER :: BC, material, ParentMaterial, BodyForce
67
INTEGER :: NBoundary, NParent, BoundaryElementNode, ParentElementNode, body_id, other_body_id, material_id
68
INTEGER :: nodenumber, NumberOfNodesOnBoundary, OldMeshTag
69
INTEGER, ALLOCATABLE :: NodeOnBoundary(:)
70
INTEGER :: Nn, i, j, p, n, Nmax, bf_id, DIM, bf_id_FS
71
REAL(KIND=dp) :: y, pw, t, told, dt, Bu, Bv
72
REAL(KIND=dp) :: Zsl, rhow, gravity
73
REAL(KIND=dp), ALLOCATABLE :: S(:), Ns(:), a_perp(:), SourceFunc(:), normal(:,:)
74
LOGICAL :: FirstTime = .TRUE., NewTime, GotIt, ComputeS, NormalFlux = .TRUE., UnFoundFatal=.TRUE., MeshChanged=.FALSE.
75
CHARACTER(LEN=MAX_NAME_LEN) :: BottomSurfaceName
76
77
SAVE told, FirstTime, NewTime, Nn, dt, Ns, Bodyforce, DIM
78
SAVE S, rhow, gravity, Zsl, NormalFlux, a_perp, SourceFunc
79
SAVE NumberOfNodesOnBoundary, NodeOnBoundary, normal
80
SAVE BottomSurfaceName, bf_id_FS, OldMeshTag
81
82
83
84
Timevar => VariableGet( Model % Variables,'Time')
85
t = TimeVar % Values(1)
86
dt = Model % Solver % dt
87
88
!Element type 101 doesn't have a parent element, can't enquire SeaLevel
89
!Should only occur during SaveBoundaryValues, so isn't an issue
90
IF(GetElementFamily(Model % CurrentElement) < 2) THEN
91
pw = 0.0_dp
92
RETURN
93
END IF
94
95
IF (FirstTime) THEN
96
NewTime = .TRUE.
97
told = t
98
99
OldMeshTag = Model % Mesh % MeshTag
100
DIM = CoordinateSystemDimension()
101
102
rhow = GetConstReal( Model % Constants, 'Water Density', GotIt )
103
IF (.NOT.GotIt) THEN
104
WRITE(Message,'(A)') 'Variable Water Density not found. &
105
&Setting to 1.03225e-18'
106
CALL INFO('SeaPressure', Message, level=20)
107
rhow = 1.03225e-18_dp
108
ELSE
109
WRITE(Message,'(A,F10.4)') 'Water Density = ', rhow
110
CALL INFO('SeaPressure', Message , level = 20)
111
END IF
112
113
!-----------------------------------------------------------------
114
! Is there basal melt to account for
115
!-----------------------------------------------------------------
116
NormalFlux = GetLogical( Model % Constants, 'Buoyancy Use Basal Melt', GotIt )
117
IF (.NOT.GotIt) THEN
118
WRITE(Message,'(A)') 'Variable Buoyancy Use Basal Melt not found. &
119
&Setting to FALSE'
120
CALL INFO('SeaPressure', Message, level=20)
121
NormalFlux = .FALSE.
122
ELSE
123
WRITE(Message,*) 'Buoyancy Use Basal Melt = ', NormalFlux
124
CALL INFO('SeaPressure', Message , level = 20)
125
END IF
126
127
!-----------------------------------------------------------------
128
! Find the bf_id of the FS solvers if NormalFlux is TRUE
129
! and read the name of the Bottom Free surface solver
130
!-----------------------------------------------------------------
131
IF (NormalFlux) THEN
132
BottomSurfaceName = GetString( Model % Constants, 'Bottom Surface Name', GotIt )
133
IF (.NOT.GotIt) THEN
134
WRITE(Message,'(A)') 'Variable Bottom SUrface Name not found. &
135
&Setting to DyBottom'
136
CALL INFO('SeaPressure', Message, level=20)
137
BottomSurfaceName = 'DyBottom'
138
ELSE
139
WRITE(Message,*)'Bottom Surface Name = ',TRIM(BottomSurfaceName)
140
CALL INFO('SeaPressure', Message , level = 20)
141
END IF
142
143
bf_id_FS = -1
144
DO bf_id=1,Model % NumberOFBodyForces
145
IF( ListCheckPresent( Model % BodyForces(bf_id) % Values, &
146
TRIM(BottomSurfaceName)//' Accumulation') ) bf_id_FS = bf_id
147
END DO
148
149
IF (bf_id_FS<0) THEN
150
CALL FATAL('Sea Pressure','No Basal Melt found in any body Force')
151
END IF
152
END IF
153
154
!-----------------------------------------------------------------
155
! Read the gravity
156
!-----------------------------------------------------------------
157
bf_id = ListGetInteger( Model % Bodies(1) % Values,&
158
'Body Force', minv=1, maxv=Model % NumberOFMaterials)
159
160
IF (DIM==2) THEN !NOT the same keyword if the shape factor is used
161
gravity = -GetConstReal( Model % BodyForces(bf_id) % Values, 'Lateral Friction Gravity 2',Gotit)
162
IF (.NOT. Gotit) THEN
163
gravity = -GetConstReal( Model % BodyForces(bf_id) % Values, 'Flow BodyForce 2',Gotit)
164
END IF
165
ELSE
166
gravity = -GetConstReal( Model % BodyForces(bf_id) % Values, 'Flow BodyForce 3',Gotit)
167
END IF
168
169
ELSE
170
IF (t > told) THEN
171
NewTime = .TRUE.
172
told = t
173
END IF
174
ENDIF ! FirstTime
175
176
IF(OldMeshTag /= Model % Mesh % MeshTag) THEN
177
OldMeshTag = Model % Mesh % MeshTag
178
MeshChanged = .TRUE.
179
END IF
180
IF(Model % Mesh % Changed) MeshChanged = .TRUE.
181
182
IF(FirstTime .OR. (NewTime .AND. MeshChanged)) THEN
183
MeshChanged = .FALSE.
184
IF(.NOT. FirstTime) &
185
DEALLOCATE(NodeOnBoundary, SourceFunc)
186
ALLOCATE( NodeOnBoundary( Model % Mesh % NumberOfNodes ))
187
n = Model % MaxElementNodes
188
ALLOCATE( SourceFunc(n) )
189
190
FirstTime = .FALSE.
191
192
!-----------------------------------------------------------------
193
! Number of nodes concerned (needed to compute Ns from the normal)
194
!-----------------------------------------------------------------
195
196
CurElement => Model % CurrentElement
197
NodeOnBoundary = 0
198
NumberOfNodesOnBoundary = 0
199
DO p = 1, Model % NumberOfBoundaryElements
200
BCElement => GetBoundaryElement(p)
201
BC => GetBC( BCElement )
202
IF( GetElementFamily(BCElement) == 1 ) CYCLE
203
ComputeS = GetLogical( BC, 'Compute Sea Pressure', GotIt)
204
IF (.Not.GotIt) ComputeS = .FALSE.
205
IF (ComputeS) THEN
206
n = BCElement % Type % NumberOfNodes
207
DO i = 1, n
208
j = BCElement % NodeIndexes (i)
209
IF (NodeOnBoundary(j)==0) THEN
210
NumberOfNodesOnBoundary = NumberOfNodesOnBoundary + 1
211
NodeOnBoundary(j) = NumberOfNodesOnBoundary
212
END IF
213
END DO
214
END IF
215
END DO
216
Model % CurrentElement => CurElement
217
218
IF(ALLOCATED(S)) DEALLOCATE(S,Ns)
219
IF(ALLOCATED(a_perp)) DEALLOCATE(a_perp)
220
221
ALLOCATE( S( NumberOfNodesOnBoundary ), Ns( NumberOfNodesOnBoundary ))
222
IF (NormalFlux) ALLOCATE( a_perp ( NumberOfNodesOnBoundary ))
223
END IF
224
225
226
IF (NewTime) THEN
227
NewTime = .FALSE.
228
229
!-----------------------------------------------------------------
230
! get some information upon active boundary element and its parent
231
!-----------------------------------------------------------------
232
BoundaryElement => Model % CurrentElement
233
IF ( .NOT. ASSOCIATED(BoundaryElement) ) THEN
234
CALL FATAL('Sea Pressure','No boundary element found')
235
END IF
236
other_body_id = BoundaryElement % BoundaryInfo % outbody
237
IF (other_body_id < 1) THEN ! only one body in calculation
238
ParentElement => BoundaryElement % BoundaryInfo % Right
239
IF ( .NOT. ASSOCIATED(ParentElement) ) ParentElement => BoundaryElement % BoundaryInfo % Left
240
ELSE ! we are dealing with a body-body boundary and assume that the normal is pointing outwards
241
ParentElement => BoundaryElement % BoundaryInfo % Right
242
IF (ParentElement % BodyId == other_body_id) ParentElement => BoundaryElement % BoundaryInfo % Left
243
END IF
244
245
body_id = ParentElement % BodyId
246
material_id = ListGetInteger(Model % Bodies(body_id) % Values, 'Material', GotIt, UnFoundFatal=UnFoundFatal)
247
ParentMaterial => Model % Materials(material_id) % Values
248
IF ((.NOT. ASSOCIATED(ParentMaterial))) THEN
249
WRITE(Message,'(A,I10,A,I10)')&
250
'No material values found for body no ', body_id,&
251
' under material id ', material_id
252
CALL FATAL('Sea Pressure',Message)
253
END IF
254
NParent = ParentElement % Type % NumberOfNodes
255
256
!-------------------------
257
! Get material parameters
258
! Sea level for that time
259
!-------------------------
260
261
Zsl = GetCReal( ParentMaterial, 'Sea level', GotIt )
262
IF (.NOT.GotIt) THEN
263
WRITE(Message,'(A)') 'Variable Sea level not found. &
264
&Setting to 0.0'
265
CALL INFO('SeaPressure', Message, level=2)
266
Zsl = 0.0_dp
267
ELSE
268
WRITE(Message,'(A,F10.4)') 'Sea level = ', Zsl
269
CALL INFO('SeaPressure', Message , level = 2)
270
END IF
271
272
!---------------------------
273
! Compute S for new t
274
!---------------------------
275
CurElement => Model % CurrentElement
276
S = 0.0
277
DO p = 1, Model % NumberOfBoundaryElements
278
BCElement => GetBoundaryElement(p)
279
BC => GetBC( BCElement )
280
IF( GetElementFamily(BCElement) == 1 ) CYCLE
281
ComputeS = GetLogical( BC, 'Compute Sea Pressure', GotIt)
282
IF (.Not.GotIt) ComputeS = .FALSE.
283
IF (ComputeS) THEN
284
n = BCElement % Type % NumberOfNodes
285
DO i = 1, n
286
j = BCElement % NodeIndexes (i)
287
IF (DIM==2) THEN
288
S(NodeOnBoundary(j)) = Model % Nodes % y (j)
289
ELSE
290
S(NodeOnBoundary(j)) = Model % Nodes % z (j)
291
END IF
292
END DO
293
END IF
294
END DO
295
Model % CurrentElement => CurElement
296
!----------------------------------------------------------------------------
297
! Compute Ns and Flux (melting) for new t
298
! Restricted to the surface below the shelf
299
! The melting is not taken into account where dS/dx is infinite (calving front)
300
!----------------------------------------------------------------------------
301
Ns = 0.0_dp
302
IF (NormalFlux) THEN
303
a_perp = 0.0_dp
304
ALLOCATE( Normal(3, NumberOfNodesOnBoundary))
305
Normal = 0.0_dp
306
CurElement => Model % CurrentElement
307
DO p = 1, Model % NumberOfBoundaryElements
308
BCElement => GetBoundaryElement(p)
309
BC => GetBC( BCElement )
310
IF( GetElementFamily(BCElement) == 1 ) CYCLE
311
ComputeS = GetLogical( BC, 'Compute Sea Spring', GotIt)
312
IF (.Not.GotIt) ComputeS = .FALSE.
313
314
! we only compute the term Ns.b if the Spring is on
315
SourceFunc = 0.0_dp
316
IF (ComputeS) THEN
317
n = BCElement % Type % NumberOfNodes
318
SourceFunc(1:n) = GetReal( Model % BodyForces(bf_id_FS) % Values, &
319
TRIM(BottomSurfaceName)//' Accumulation', GotIt)
320
321
CALL GetElementNodes( Nodes , BCElement )
322
DO i = 1,n
323
j = BCElement % NodeIndexes( i )
324
Bu = BCElement % Type % NodeU(i)
325
IF ( BCElement % Type % Dimension > 1 ) THEN
326
Bv = BCElement % Type % NodeV(i)
327
ELSE
328
Bv = 0.0D0
329
END IF
330
Normal(:,NodeOnBoundary(j)) = Normal(:,NodeOnBoundary(j)) + &
331
NormalVector(BCElement, Nodes, Bu, Bv, .TRUE.)
332
a_perp( NodeOnBoundary(j) ) = SourceFunc (i)
333
END DO
334
END IF
335
END DO
336
337
DO i=1, NumberOfNodesOnBoundary
338
IF (ABS(Normal(DIM,i)) > 1.0e-20_dp) THEN
339
Ns(i) = 1.0_dp + (Normal(1,i)/Normal(DIM,i))**2.0_dp
340
IF (DIM>2) THEN
341
Ns(i) = Ns(i) + (Normal(2,i)/Normal(3,i))**2.0_dp
342
END IF
343
Ns(i) = SQRT(Ns(i))
344
ELSE
345
Ns(i) = -999.0
346
END IF
347
END DO
348
DEALLOCATE (Normal)
349
Model % CurrentElement => CurElement
350
END IF
351
ENDIF ! new dt
352
353
j = NodeOnBoundary( nodenumber )
354
IF ( NormalFlux .AND. (Ns(j) > 0.0_dp)) THEN
355
pw = -gravity * rhow * (Zsl - S(j) - a_perp(j) * dt * Ns(j) )
356
ELSE
357
pw = -gravity * rhow * (Zsl - S(j))
358
END IF
359
IF (pw > 0.0) pw = 0.0
360
361
END FUNCTION SeaPressure
362
363
364
365
FUNCTION SeaSpring ( Model, nodenumber, y) RESULT(C)
366
USE types
367
USE CoordinateSystems
368
USE SolverUtils
369
USE ElementDescription
370
USE DefUtils
371
IMPLICIT NONE
372
TYPE(Model_t) :: Model
373
TYPE(Solver_t):: Solver
374
TYPE(Nodes_t), SAVE :: Nodes
375
TYPE(variable_t), POINTER :: Timevar, NormalSolution
376
TYPE(Element_t), POINTER :: BoundaryElement, BCElement, CurElement, ParentElement
377
TYPE(ValueList_t), POINTER :: BC, material, ParentMaterial, BodyForce
378
INTEGER :: NBoundary, NParent, BoundaryElementNode, ParentElementNode, body_id, other_body_id, material_id
379
INTEGER :: nodenumber, NumberOfNodesOnBoundary
380
INTEGER, ALLOCATABLE :: NodeOnBoundary(:)
381
INTEGER :: Nn, i, j, k, p, n, Nmax, bf_id, DIM, OldMeshTag
382
REAL(KIND=dp) :: y, C, t, told, dt, Bu, Bv, aux
383
REAL(KIND=dp) :: rhow, gravity, Nsi, NodeNormal(3)
384
REAL(KIND=dp), ALLOCATABLE :: Ns(:), normal(:,:)
385
LOGICAL :: FirstTime = .TRUE., NewTime, GotIt, ComputeS,MeshChanged=.FALSE.
386
387
SAVE told, FirstTime, NewTime, Nn, dt, Ns, Bodyforce, DIM
388
SAVE rhow, gravity
389
SAVE NumberOfNodesOnBoundary, NodeOnBoundary, normal,OldMeshTag
390
SAVE NormalSolution
391
392
Timevar => VariableGet( Model % Variables,'Time')
393
t = TimeVar % Values(1)
394
395
aux = GetConstReal(Model % Constants, 'Sea Spring Timestep Size', GotIt)
396
IF (GotIt) THEN
397
dt = aux
398
ELSE
399
dt = Model % Solver % dt
400
END IF
401
402
!Element type 101 doesn't have a parent element, can't enquire SeaLevel
403
!Should only occur during SaveBoundaryValues, so isn't an issue
404
IF(GetElementFamily(Model % CurrentElement) < 2) THEN
405
C = 1.0e20_dp
406
RETURN
407
END IF
408
409
! .OR. (NewTime .AND. Model % Mesh % Changed)
410
IF(FirstTime) THEN
411
NewTime = .TRUE.
412
OldMeshTag = Model % Mesh % MeshTag
413
ELSE IF(t > told) THEN
414
NewTime = .TRUE.
415
told = t
416
END IF
417
418
IF(OldMeshTag .NE. Model % Mesh % MeshTag) THEN
419
OldMeshTag = Model % Mesh % MeshTag
420
MeshChanged = .TRUE.
421
END IF
422
IF(Model % Mesh % Changed) MeshChanged = .TRUE.
423
424
IF (FirstTime .OR. (NewTime .AND. MeshChanged)) THEN
425
NormalSolution => VariableGet( Model % Variables, 'Normal Vector')
426
427
IF(.NOT. FirstTime) DEALLOCATE(NodeOnBoundary, Ns)
428
FirstTime = .FALSE.
429
NewTime = .FALSE.
430
431
ALLOCATE( NodeOnBoundary( Model % Mesh % NumberOfNodes ))
432
n = Model % MaxElementNodes
433
434
DIM = CoordinateSystemDimension()
435
436
rhow = GetConstReal( Model % Constants, 'Water Density', GotIt )
437
IF (.NOT.GotIt) THEN
438
WRITE(Message,'(A)') 'Variable "Water Density" not found in Constants.'
439
CALL FATAL('SeaSpring', Message)
440
ELSE
441
WRITE(Message,'(A,F10.4)') 'Water Density = ', rhow
442
CALL INFO('SeaSpring', Message , level = 20)
443
END IF
444
445
!-----------------------------------------------------------------
446
! get some information upon active boundary element and its parent
447
!-----------------------------------------------------------------
448
BoundaryElement => Model % CurrentElement
449
IF ( .NOT. ASSOCIATED(BoundaryElement) ) THEN
450
CALL FATAL('SeaSpring','No boundary element found')
451
END IF
452
other_body_id = BoundaryElement % BoundaryInfo % outbody
453
IF (other_body_id < 1) THEN ! only one body in calculation
454
ParentElement => BoundaryElement % BoundaryInfo % Right
455
IF ( .NOT. ASSOCIATED(ParentElement) ) ParentElement => BoundaryElement % BoundaryInfo % Left
456
ELSE ! we are dealing with a body-body boundary and assume that the normal is pointing outwards
457
ParentElement => BoundaryElement % BoundaryInfo % Right
458
IF (ParentElement % BodyId == other_body_id) ParentElement => BoundaryElement % BoundaryInfo % Left
459
END IF
460
461
BodyForce => GetBodyForce(ParentElement)
462
bf_id = ListGetInteger( Model % Bodies(1) % Values,&
463
'Body Force', minv=1, maxv=Model % NumberOFMaterials)
464
IF (DIM==2) THEN !NOT the same keyword if the shape factor is used
465
gravity = -GetConstReal( Model % BodyForces(bf_id) % Values, 'Lateral Friction Gravity 2',Gotit)
466
IF (.NOT. Gotit) THEN
467
gravity = -GetConstReal( Model % BodyForces(bf_id) % Values, 'Flow BodyForce 2',Gotit)
468
END IF
469
ELSE
470
gravity = -GetConstReal( Model % BodyForces(bf_id) % Values, 'Flow BodyForce 3',Gotit)
471
END IF
472
473
! Number of node concerned
474
475
CurElement => Model % CurrentElement
476
NodeOnBoundary = 0
477
NumberOfNodesOnBoundary = 0
478
DO p = 1, Model % NumberOfBoundaryElements
479
BCElement => GetBoundaryElement(p)
480
BC => GetBC( BCElement )
481
IF( GetElementFamily(BCElement) == 1 ) CYCLE
482
ComputeS = GetLogical( BC, 'Compute Sea Spring', GotIt)
483
IF (.Not.GotIt) ComputeS = .FALSE.
484
485
486
IF (ComputeS) THEN
487
n = BCElement % Type % NumberOfNodes
488
DO i = 1, n
489
j = BCElement % NodeIndexes (i)
490
IF (NodeOnBoundary(j)==0) THEN
491
NumberOfNodesOnBoundary = NumberOfNodesOnBoundary + 1
492
NodeOnBoundary(j) = NumberOfNodesOnBoundary
493
END IF
494
END DO
495
END IF
496
END DO
497
Model % CurrentElement => CurElement
498
499
ALLOCATE( Ns( NumberOfNodesOnBoundary ))
500
501
! Compute Ns for new t
502
ALLOCATE( Normal(3, NumberOfNodesOnBoundary))
503
Ns = 0.0_dp
504
Normal = 0.0_dp
505
CurElement => Model % CurrentElement
506
DO p = 1, Model % NumberOfBoundaryElements
507
BCElement => GetBoundaryElement(p)
508
BC => GetBC( BCElement )
509
IF( GetElementFamily(BCElement) == 1 ) CYCLE
510
ComputeS = GetLogical( BC, 'Compute Sea Spring', GotIt)
511
IF (.Not.GotIt) ComputeS = .FALSE.
512
IF (ComputeS) THEN
513
CALL GetElementNodes( Nodes , BCElement )
514
n = BCElement % Type % NumberOfNodes
515
DO i = 1,n
516
j = BCElement % NodeIndexes( i )
517
Bu = BCElement % Type % NodeU(i)
518
IF ( BCElement % TYPE % DIMENSION > 1 ) THEN
519
Bv = BCElement % Type % NodeV(i)
520
ELSE
521
Bv = 0.0D0
522
END IF
523
Normal(:,NodeOnBoundary(j)) = Normal(:,NodeOnBoundary(j)) + &
524
NormalVector(BCElement, Nodes, Bu, Bv, .TRUE.)
525
END DO
526
END IF
527
END DO
528
529
DO i=1, NumberOfNodesOnBoundary
530
IF (ABS(Normal(DIM,i)) > 1.0e-20_dp) THEN
531
Ns(i) = 1.0_dp + (Normal(1,i)/Normal(DIM,i))**2.0_dp
532
IF (DIM>2) THEN
533
Ns(i) = Ns(i) + (Normal(2,i)/Normal(3,i))**2.0_dp
534
END IF
535
Ns(i) = SQRT(Ns(i))
536
ELSE
537
Ns(i) = -999.0_dp
538
CALL WARN('SeaSpring', 'Lower surface almost is vertically aligned')
539
END IF
540
END DO
541
542
DEALLOCATE (Normal)
543
Model % CurrentElement => CurElement
544
545
ENDIF ! new dt
546
547
548
GotIt = .FALSE.
549
Nsi = -999.0_dp
550
551
! Get consistent normal if it is available on all nodes.
552
! This is rather dirty since the other stuff is done anyways, even if this would
553
! concern all the nodes.
554
NodeNormal = ConsistentNormalVector( CurrentModel % Solver, NormalSolution, &
555
Model % CurrentElement, GotIt, Node = NodeNumber )
556
IF( GotIt ) THEN
557
IF(ABS(NodeNormal(dim)) > 1.0e-20_dp) THEN
558
Nsi = SQRT( 1.0_dp + (SUM(NodeNormal(1:dim-1)**2)) / NodeNormal(dim)**2.0_dp )
559
GotIt = .TRUE.
560
END IF
561
END IF
562
563
IF(.NOT. GotIt ) THEN
564
j = NodeOnBoundary( nodenumber )
565
IF( j > 0 ) Nsi = Ns(j)
566
END IF
567
568
IF( Nsi > 0.0_dp ) THEN
569
C = gravity * rhow * dt * Nsi
570
ELSE
571
C = 1.0e20_dp
572
END IF
573
574
END FUNCTION SeaSpring
575
576