Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/Flowdepth.F90
3203 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: Thomas Zwinger, Martina Schäfer
26
! * Email: [email protected]
27
! * Web: http://elmerice.elmerfem.org
28
! * Address: CSC - Scientific Computing Ltd.
29
! * Keilaranta 14
30
! * 02101 Espoo, Finland
31
! *
32
! * Original Date:
33
! *
34
! ****************************************************************************/
35
!> FlowDepthSolver: Solver to inquire the vertical distance from a line (2d)
36
!> or surface (3d). Solves a degenerated Poisson-equation
37
SUBROUTINE FlowdepthSolver( Model,Solver,dt,TransientSimulation )
38
!------------------------------------------------------------------------------
39
!******************************************************************************
40
!
41
! Solve the Flowdepth equation!
42
!
43
! ARGUMENTS:
44
!
45
! TYPE(Model_t) :: Model,
46
! INPUT: All model information (mesh, materials, BCs, etc...)
47
!
48
! TYPE(Solver_t) :: Solver
49
! INPUT: Linear & nonlinear equation solver options
50
!
51
! REAL(KIND=dp) :: dt,
52
! INPUT: Timestep size for time dependent simulations
53
!
54
! LOGICAL :: TransientSimulation
55
! INPUT: Steady state or transient simulation
56
!
57
!******************************************************************************
58
USE DefUtils
59
60
IMPLICIT NONE
61
!------------------------------------------------------------------------------
62
TYPE(Solver_t), TARGET :: Solver
63
TYPE(Model_t) :: Model
64
65
REAL(KIND=dp) :: dt
66
LOGICAL :: TransientSimulation
67
!------------------------------------------------------------------------------
68
! Local variables
69
!------------------------------------------------------------------------------
70
TYPE(Element_t),POINTER :: Element
71
TYPE(ValueList_t), POINTER :: SolverParams, BC
72
TYPE(Variable_t), POINTER :: PointerToVariable, Grad1Sol, Grad2Sol, SurfSol
73
TYPE(Solver_t), POINTER :: PointerToSolver
74
75
LOGICAL :: AllocationsDone = .FALSE., Found, CalcFree = .FALSE., GotIt, SkipBoundary
76
77
INTEGER :: i, n, m, t, istat, DIM
78
INTEGER, POINTER :: Permutation(:), NumberOfVisits(:),&
79
SurfacePerm(:), GradSurface1Perm(:),GradSurface2Perm(:)
80
81
REAL(KIND=dp), POINTER :: VariableValues(:), Surface(:), GradSurface1(:),GradSurface2(:)
82
REAL(KIND=dp) :: Norm, Gradient,GradSurface(3)
83
84
REAL(KIND=dp), ALLOCATABLE :: STIFF(:,:), LOAD(:), FORCE(:)
85
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName, FreeSurfName, FreeSurfGradName
86
87
88
SAVE STIFF, LOAD, FORCE, AllocationsDone, DIM, SolverName, NumberOfVisits
89
!------------------------------------------------------------------------------
90
PointerToSolver => Solver
91
PointerToVariable => Solver % Variable
92
Permutation => PointerToVariable % Perm
93
VariableValues => PointerToVariable % Values
94
95
!--------------------------------------------------------------
96
!Allocate some permanent storage, this is done first time only:
97
!--------------------------------------------------------------
98
IF ( (.NOT. AllocationsDone) .OR. Solver % Mesh % Changed ) THEN
99
DIM = CoordinateSystemDimension()
100
WRITE(SolverName, '(A)') 'FlowdepthSolver'
101
N = Solver % Mesh % MaxElementNodes ! just big enough for elemental arrays
102
M = Model % Mesh % NumberOfNodes
103
IF (AllocationsDone) DEALLOCATE(FORCE, LOAD, STIFF, NumberOfVisits)
104
105
ALLOCATE( FORCE(N), LOAD(N), STIFF(N,N), NumberOfVisits(M),&
106
STAT=istat )
107
IF ( istat /= 0 ) THEN
108
CALL Fatal( SolverName, 'Memory allocation error.' )
109
END IF
110
111
AllocationsDone = .TRUE.
112
CALL INFO( SolverName, 'Memory allocation done.',Level=1 )
113
END IF
114
115
!----------------------------------
116
! get Gradient (change of property
117
! with respect to unit-length of
118
! vertical direction
119
!----------------------------------
120
SolverParams => GetSolverParams()
121
Gradient = GetConstReal( SolverParams, &
122
'Gradient', Found )
123
IF (.NOT. Found) THEN
124
CALL WARN(SolverName, 'No keyword >Gradient< found in section Solver')
125
CALL WARN(SolverName, 'Assuming value of -1')
126
Gradient = -1.0D00
127
ELSE
128
WRITE(Message,'(A,e12.4,A)') 'Gradient of ',Gradient,' applied'
129
CALL INFO(SolverName, Message,Level=1)
130
END IF
131
!----------------------------------------------------------------
132
! Assign Variables for computations of free surface and gradients
133
!----------------------------------------------------------------
134
CalcFree = GetLogical(SolverParams, 'Calc Free Surface', Found)
135
IF (.NOT.Found) THEN
136
CalcFree = .FALSE.
137
ELSE
138
IF (CalcFree) THEN
139
CALL INFO(SolverName, 'Free surface variable will be calculated', Level=1)
140
FreeSurfName = GetString( Solver % Values,'Freesurf Name',GotIt)
141
IF (.NOT.GotIt) THEN
142
CALL FATAL(SolverName,'Keyaword >Calc Free Surface< set to true, but keyword >Freesurf Name< not found.')
143
END IF
144
145
SurfSol => VariableGet( Solver % Mesh % Variables, TRIM(FreeSurfname))
146
IF (ASSOCIATED(SurfSol)) THEN
147
Surface => SurfSol % Values
148
SurfacePerm => SurfSol % Perm
149
ELSE
150
ALLOCATE(Surface(M), STAT=istat )
151
SurfacePerm => Permutation
152
IF ( istat /= 0 ) THEN
153
CALL Fatal( SolverName, 'Memory allocation error.' )
154
END IF
155
CALL VariableAdd( Solver % Mesh % Variables, Solver % Mesh, PointerToSolver, &
156
TRIM(FreeSurfname), 1, Surface, SurfacePerm)
157
END IF
158
159
FreeSurfGradName = TRIM(FreeSurfname) // 'Grad1'
160
Grad1Sol => VariableGet( Solver % Mesh % Variables, FreeSurfGradName)
161
IF (ASSOCIATED(Grad1Sol)) THEN
162
GradSurface1 => Grad1Sol % Values
163
GradSurface1Perm => Grad1Sol % Perm
164
ELSE
165
ALLOCATE(GradSurface1(M), STAT=istat )
166
GradSurface1Perm => Permutation
167
IF ( istat /= 0 ) THEN
168
CALL Fatal( SolverName, 'Memory allocation error.' )
169
END IF
170
CALL VariableAdd( Solver % Mesh % Variables, Solver % Mesh, PointerToSolver, &
171
TRIM(FreeSurfGradName), 1, GradSurface1, GradSurface1Perm)
172
END IF
173
FreeSurfGradName = TRIM(FreeSurfname) // 'Grad2'
174
Grad2Sol => VariableGet( Solver % Mesh % Variables, FreeSurfGradName)
175
IF (ASSOCIATED(Grad2Sol)) THEN
176
GradSurface2 => Grad2Sol % Values
177
GradSurface2Perm => Grad2Sol % Perm
178
ELSE
179
ALLOCATE(GradSurface2(M), STAT=istat )
180
GradSurface2Perm => Permutation
181
IF ( istat /= 0 ) THEN
182
CALL Fatal( SolverName, 'Memory allocation error.' )
183
END IF
184
CALL VariableAdd( Solver % Mesh % Variables, Solver % Mesh, PointerToSolver, &
185
TRIM(FreeSurfGradName), 1, GradSurface2, GradSurface2Perm)
186
END IF
187
!---------------
188
! initialization
189
!---------------
190
Surface = 1.0D00
191
GradSurface1 = 2.0D00
192
GradSurface2 = 3.0D00
193
END IF
194
END IF
195
196
197
!Initialize the system and do the assembly:
198
!------------------------------------------
199
CALL DefaultInitialize()
200
! bulk assembly
201
DO t=1,Solver % NumberOfActiveElements
202
Element => GetActiveElement(t)
203
IF (ParEnv % myPe .NE. Element % partIndex) CYCLE
204
n = GetElementNOFNodes()
205
CALL LocalMatrix( STIFF, FORCE, Element, n)
206
CALL DefaultUpdateEquations( STIFF, FORCE )
207
END DO
208
209
! Neumann conditions
210
DO t=1,Solver % Mesh % NUmberOfBoundaryElements
211
Element => GetBoundaryElement(t)
212
IF (ParEnv % myPe .NE. Element % partIndex) CYCLE
213
BC => GetBC(Element)
214
SkipBoundary = GetLogical(BC, &
215
'Flowdepth Skip', Found )
216
IF (.NOT.Found) SkipBoundary = .FALSE.
217
IF (SkipBoundary) CYCLE
218
n = GetElementNOFNodes()
219
STIFF = 0.0D00
220
FORCE = 0.0D00
221
! only select elements with defined normals with respect to the dimension of the problem
222
IF( GetElementFamily() .GE. DIM) &
223
CALL LocalMatrixBC( STIFF, FORCE, Element, n, Gradient)
224
CALL DefaultUpdateEquations( STIFF, FORCE )
225
END DO
226
227
CALL DefaultFinishAssembly()
228
229
! Dirichlet
230
CALL DefaultDirichletBCs()
231
232
!Solve the system
233
Norm = DefaultSolve()
234
235
!--------------------------------------------------------
236
! post-processing steps for free surface and its gradient
237
!--------------------------------------------------------
238
IF (Calcfree) THEN
239
Surface = 0.0D00
240
GradSurface1 = 0.0D00
241
GradSurface2 = 0.0D00
242
NumberOfVisits = 0
243
DO t=1,Solver % NumberOfActiveElements
244
Element => GetActiveElement(t)
245
n = GetElementNOFNodes()
246
CALL GetSurfaceValue(Model, Surface, GradSurface1, GradSurface2,&
247
VariableValues, Permutation, &
248
SurfacePerm, GradSurface1Perm, GradSurface2Perm, &
249
NumberOfVisits, Element, n, Gradient )
250
END DO
251
DO i=1,Model % Mesh % NumberOfNodes
252
GradSurface1(GradSurface1Perm(i)) = GradSurface1(GradSurface1Perm(i))/NumberOfVisits(i)
253
GradSurface2(GradSurface2Perm(i)) = GradSurface2(GradSurface2Perm(i))/NumberOfVisits(i)
254
END DO
255
END IF
256
CONTAINS
257
258
!------------------------------------------------------------------------------
259
SUBROUTINE GetSurfaceValue(Model, Surface, GradSurface1, GradSurface2, &
260
VariableValues, Permutation, &
261
SurfacePerm, GradSurface1Perm, GradSurface2Perm, &
262
NumberOfVisits, Element, n, Gradient )
263
!------------------------------------------------------------------------------
264
TYPE(Model_t) :: Model
265
REAL(KIND=dp) :: LocalSurf, GradSurface(3), Depth, Gradient
266
INTEGER :: n
267
INTEGER, POINTER :: Permutation(:), NumberOfVisits(:), &
268
SurfacePerm(:), GradSurface1Perm(:), GradSurface2Perm(:)
269
REAL(KIND=dp), POINTER :: Surface(:), GradSurface1(:), GradSurface2(:), VariableValues(:)
270
TYPE(Element_t), POINTER :: Element
271
!------------------------------------------------------------------------------
272
REAL(KIND=dp) :: Basis(n),dBasisdx(n,3),ddBasisddx(n,3,3),DetJ,&
273
z, U, V, W, SqrtElementMetric
274
LOGICAL :: Stat
275
INTEGER :: i,j,k,dim
276
LOGICAL :: FirstTime
277
TYPE(Nodes_t) :: Nodes
278
SAVE Nodes
279
!------------------------------------------------------------------------------
280
CALL GetElementNodes( Nodes )
281
282
dim = CoordinateSystemDimension()
283
! loop over all nodes in Element
284
DO i=1,N
285
286
j = Element % NodeIndexes(i) ! get number of node in element in physical space
287
NumberOfVisits(j) = NumberOfVisits(j) + 1
288
289
! get local coordinates of the point i inside the element
290
U = Element % Type % NodeU(i)
291
V = Element % Type % NodeV(i)
292
W = Element % Type % NodeW(i)
293
294
! get local information on test-functions and derivatives of the point i
295
stat = ElementInfo( Element,Nodes,U,V,W,SqrtElementMetric, &
296
Basis,dBasisdx,ddBasisddx,.FALSE.,.FALSE. )
297
IF (DIM == 2) THEN
298
z = Model % Nodes % y(j)
299
ELSE IF (DIM == 3) THEN
300
z = Model % Nodes % z(j)
301
ELSE
302
CALL FATAL(SolverName, 'Flow depth for one-dimensional problem not defined!')
303
END IF
304
305
IF (NumberOfVisits(j) == 1) &
306
Surface(SurfacePerm(j)) = z -VariableValues(Permutation(j))/Gradient
307
308
GradSurface1(GradSurface1Perm(j)) = GradSurface1(GradSurface1Perm(j)) +&
309
SUM(dBasisdx(1:N,1)*VariableValues(Permutation(Element % NodeIndexes(1:N))))/abs(Gradient)
310
311
IF (DIM > 2) &
312
GradSurface2(GradSurface1Perm(j)) = GradSurface2(GradSurface1Perm(j)) +&
313
SUM(dBasisdx(1:N,2)*VariableValues(Permutation(Element % NodeIndexes(1:N))))/abs(Gradient)
314
END DO
315
!------------------------------------------------------------------------------
316
END SUBROUTINE GetSurfaceValue
317
!------------------------------------------------------------------------------
318
319
320
!------------------------------------------------------------------------------
321
SUBROUTINE LocalMatrix( STIFF, FORCE, Element, n)
322
!------------------------------------------------------------------------------
323
REAL(KIND=dp) :: STIFF(:,:), FORCE(:)
324
INTEGER :: n
325
TYPE(Element_t), POINTER :: Element
326
!------------------------------------------------------------------------------
327
REAL(KIND=dp) :: Basis(n),dBasisdx(n,3),ddBasisddx(n,3,3),DetJ
328
LOGICAL :: Stat
329
INTEGER :: t, p,q ,dim
330
TYPE(GaussIntegrationPoints_t) :: IP
331
332
TYPE(Nodes_t) :: Nodes
333
SAVE Nodes
334
!------------------------------------------------------------------------------
335
CALL GetElementNodes( Nodes )
336
STIFF = 0.0d0
337
FORCE = 0.0d0
338
339
dim = CoordinateSystemDimension()
340
341
IP = GaussPoints( Element )
342
DO t=1,IP % n
343
stat = ElementInfo( Element, Nodes, IP % U(t), IP % V(t), &
344
IP % W(t), detJ, Basis, dBasisdx, ddBasisddx, .FALSE. )
345
346
DO p=1,n
347
DO q=1,n
348
STIFF(p,q) = STIFF(p,q) + IP % S(t) * detJ * dBasisdx(q,dim)*dBasisdx(p,dim)
349
END DO
350
END DO
351
END DO
352
!------------------------------------------------------------------------------
353
END SUBROUTINE LocalMatrix
354
!------------------------------------------------------------------------------
355
356
357
!------------------------------------------------------------------------------
358
SUBROUTINE LocalMatrixBC( STIFF, FORCE, Element, n, Gradient)
359
!------------------------------------------------------------------------------
360
REAL(KIND=dp) :: STIFF(:,:), FORCE(:), Gradient
361
INTEGER :: n
362
TYPE(Element_t), POINTER :: Element
363
!------------------------------------------------------------------------------
364
REAL(KIND=dp) :: Basis(n),dBasisdx(n,3),ddBasisddx(n,3,3), &
365
DetJ,Normal(3)
366
LOGICAL :: Stat
367
INTEGER :: t, dim
368
TYPE(GaussIntegrationPoints_t) :: IP
369
370
TYPE(Nodes_t) :: Nodes
371
SAVE Nodes
372
!------------------------------------------------------------------------------
373
CALL GetElementNodes( Nodes )
374
STIFF = 0.0d0
375
FORCE = 0.0d0
376
377
dim = CoordinateSystemDimension()
378
379
IP = GaussPoints( Element )
380
DO t=1,IP % n
381
stat = ElementInfo( Element, Nodes, IP % U(t), IP % V(t), &
382
IP % W(t), detJ, Basis, dBasisdx, ddBasisddx, .FALSE. )
383
384
Normal = NormalVector( Element, Nodes, IP % U(t), IP % V(t), .TRUE.)
385
FORCE(1:n) = FORCE(1:n) + Gradient * IP % s(t) * DetJ * Normal(dim) * Basis(1:n)
386
END DO
387
!------------------------------------------------------------------------------
388
END SUBROUTINE LocalMatrixBC
389
!------------------------------------------------------------------------------
390
END SUBROUTINE FlowdepthSolver
391
!------------------------------------------------------------------------------
392
393
394
395
396