Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/AdjointSSA/AdjointSSA_GradientSolver.F90
3206 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: [email protected]
27
! * Web: http://elmerice.elmerfem.org
28
! *
29
! * Original Date: 30. April 2010
30
! *
31
! *****************************************************************************
32
SUBROUTINE AdjointSSA_GradientSolver_init0(Model,Solver,dt,TransientSimulation )
33
!------------------------------------------------------------------------------
34
USE DefUtils
35
IMPLICIT NONE
36
!------------------------------------------------------------------------------
37
TYPE(Solver_t), TARGET :: Solver
38
TYPE(Model_t) :: Model
39
REAL(KIND=dp) :: dt
40
LOGICAL :: TransientSimulation
41
!------------------------------------------------------------------------------
42
! Local variables
43
!------------------------------------------------------------------------------
44
CHARACTER(LEN=MAX_NAME_LEN) :: Name
45
46
Name = ListGetString( Solver % Values, 'Equation',UnFoundFatal=.TRUE.)
47
CALL ListAddNewString( Solver % Values,'Variable',&
48
'-nooutput '//TRIM(Name)//'_var')
49
CALL ListAddLogical(Solver % Values, 'Optimize Bandwidth',.FALSE.)
50
51
END SUBROUTINE AdjointSSA_GradientSolver_init0
52
! *****************************************************************************
53
SUBROUTINE AdjointSSA_GradientSolver( Model,Solver,dt,TransientSimulation )
54
!------------------------------------------------------------------------------
55
! Compute the Gradient of user defined cost functions with respect to various
56
! input parameters of the SSA model:
57
!
58
!
59
! OUTPUT is : (OPTIONAL) DJDBeta (gradient wr to slip coeff)
60
! (OPTIONAL) DJDZs (gradient wr to Zs)
61
! (OPTIONAL) DJDZb (gradient wr to Zb)
62
! (OPTIONAL) DJDRho (gradient wr to Mean Density)
63
! (OPTIONAL) DJDEta (gradient wr to Mean Viscosity)
64
!
65
! BE careful: - change of variable (for example slip coeff = 10^alpha) has to
66
! be taken care by the user in the .sif
67
! - by default the gradient is reset to 0 here; set "Reset DJD... = Logical False"
68
! if part of the gradient has already been computed before
69
!
70
!
71
! INPUT PARAMETERS are (in addition to the SSA required INPUTS):
72
!
73
! In solver section:
74
! Flow Solution Name = String (default SSAVelocity)
75
! Adjoint Solution Name = String (default Adjoint)
76
!
77
! Compute DJDBeta = Logical (default False)
78
! Reset DJDBeta = Logical (default True)
79
!
80
! Compute DJDZs = Logical (default False)
81
! Reset DJDZs = Logical (default True)
82
!
83
! Compute DJDZb = Logical (default False)
84
! Reset DJDZb = Logical (default True)
85
!
86
! Compute DJDRho = Logical (default False)
87
! Reset DJDRho = Logical (default True)
88
!
89
! Compute DJDEta = Logical (default False)
90
! Reset DJDEta = Logical (default True)
91
!
92
!
93
!
94
!******************************************************************************
95
!
96
! ARGUMENTS:
97
!
98
! TYPE(Model_t) :: Model,
99
! INPUT: All model information (mesh, materials, BCs, etc...)
100
!
101
! TYPE(Solver_t) :: Solver
102
! INPUT: Linear & nonlinear equation solver options
103
!
104
! REAL(KIND=dp) :: dt,
105
! INPUT: Timestep size for time dependent simulations
106
!
107
! LOGICAL :: TransientSimulation
108
! INPUT: Steady state or transient simulation
109
!
110
!******************************************************************************
111
USE DefUtils
112
113
IMPLICIT NONE
114
!------------------------------------------------------------------------------
115
TYPE(Solver_t) :: Solver
116
TYPE(Model_t) :: Model
117
118
REAL(KIND=dp) :: dt
119
LOGICAL :: TransientSimulation
120
!------------------------------------------------------------------------------
121
! Local variables
122
!------------------------------------------------------------------------------
123
TYPE(Solver_t), POINTER :: DSolver
124
TYPE(Nodes_t) :: ElementNodes
125
TYPE(Element_t),POINTER :: CurrentElement, Element, ParentElement, BoundaryElement
126
TYPE(Matrix_t),POINTER :: StiffMatrix
127
TYPE(ValueList_t), POINTER :: SolverParams, BodyForce, Material, BC
128
TYPE(Variable_t), POINTER :: ZsSol, ZbSol, &
129
VeloSolN,VeloSolD,&
130
DJDBetaSol,DJDZsSol,DJDZbSol,DJDRhoSol,DJDEtaSol
131
132
LOGICAL :: AllocationsDone = .FALSE., Found, GotIt, CalvingFront
133
LOGICAL :: Newton
134
135
INTEGER :: i, n, m, t, istat, DIM, p, STDOFs
136
INTEGER :: NonlinearIter, NewtonIter, iter, other_body_id
137
138
INTEGER, POINTER :: ZsPerm(:), ZbPerm(:), &
139
VeloNPerm(:),VeloDPerm(:),&
140
DJDBetaPerm(:),DJDZsPerm(:),DJDZbPerm(:), DJDRhoPerm(:),DJDEtaPerm(:),&
141
NodeIndexes(:)
142
143
REAL(KIND=dp), POINTER :: ForceVector(:)
144
REAL(KIND=dp), POINTER :: Zs(:), Zb(:)
145
REAL(KIND=dp), POINTER :: DJDBeta(:),DJDZs(:),DJDZb(:),DJDRho(:),DJDEta(:),VelocityN(:),VelocityD(:)
146
147
REAL(KIND=dp) :: UNorm, cn, dd, NonlinearTol, NewtonTol, MinSRInv, rhow, sealevel, &
148
PrevUNorm, relativeChange,minv
149
150
REAL(KIND=dp), ALLOCATABLE :: STIFF(:,:), LOAD(:), FORCE(:), &
151
NodalGravity(:), NodalViscosity(:), NodalDensity(:), &
152
NodalZs(:), NodalZb(:), NodalGM(:),NodalBed(:), &
153
NodalU(:), NodalV(:), NodalBeta(:),LocalLinVelo(:),&
154
Nodalbetab(:),Nodalzsb(:),Nodalzbb(:),NodalRhob(:),NodalEtab(:),&
155
NodalEtaDer(:),NodalBetaDer(:)
156
157
INTEGER :: iFriction
158
REAL(KIND=dp) :: fm
159
CHARACTER(LEN=MAX_NAME_LEN) :: Friction
160
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName='AdjointSSA_GradientSolver'
161
REAL(KIND=dp) :: at, at0
162
LOGICAL :: SEP ! Sub-element parametrization for Grounding line
163
INTEGER :: GLnIP ! number of Integ. Points for GL Sub-element parametrization
164
TYPE(Variable_t), POINTER :: GMSol,BedrockSol
165
166
LOGICAL , SAVE :: ComputeDJDBeta,ComputeDJDZs,ComputeDJDZb,ComputeDJDRho,ComputeDJDEta,Reset
167
LOGICAL :: HaveBetaDer,HaveEtaDer
168
CHARACTER(LEN=MAX_NAME_LEN), SAVE :: NeumannSolName,AdjointSolName,SName
169
INTEGER,SAVE :: SolverInd
170
171
SAVE rhow,sealevel
172
SAVE STIFF, LOAD, FORCE, AllocationsDone, DIM, SolverName, ElementNodes
173
SAVE NodalGravity, NodalViscosity, NodalDensity, &
174
NodalZs, NodalZb, NodalGM,NodalBed, &
175
NodalU, NodalV, NodeIndexes, NodalBeta,LocalLinVelo, &
176
Nodalbetab,Nodalzsb,NodalZbb,NodalRhob,NodalEtab,&
177
NodalEtaDer,NodalBetaDer
178
SAVE STDOFs
179
180
!------------------------------------------------------------------------------
181
! Get variables needed for solution
182
!------------------------------------------------------------------------------
183
DIM = CoordinateSystemDimension()
184
185
186
187
188
!!!!!!!!!!! get Solver Variables
189
SolverParams => GetSolverParams()
190
!--------------------------------------------------------------
191
!Allocate some permanent storage, this is done first time only:
192
!--------------------------------------------------------------
193
IF ( (.NOT. AllocationsDone) .OR. Solver % Mesh % Changed ) THEN
194
195
NeumannSolName = GetString( SolverParams,'Flow Solution Name', Found)
196
IF(.NOT.Found) THEN
197
CALL WARN(SolverName,'Keyword >Flow Solution Name< not found in section >Solver<')
198
CALL WARN(SolverName,'Taking default value >SSAVelocity<')
199
WRITE(NeumannSolName,'(A)') 'SSAVelocity'
200
END IF
201
!! SSA Solution
202
VeloSolN => VariableGet( Solver % Mesh % Variables, TRIM(NeumannSolName), UnFoundFatal=.TRUE. )
203
STDOFs = VeloSolN % DOFs
204
205
! Get the Direct solver
206
DO i=1,Model % NumberOfSolvers
207
if (TRIM(NeumannSolName) == TRIM(Model % Solvers(i) % Variable % Name)) exit
208
End do
209
if (i.eq.(Model % NumberOfSolvers+1)) CALL FATAL(SolverName,'Could not find Flow Solver Equation Name')
210
SolverInd=i
211
212
AdjointSolName = GetString( SolverParams,'Adjoint Solution Name', Found)
213
IF(.NOT.Found) THEN
214
CALL WARN(SolverName,'Keyword >Adjoint Solution Name< not found in section >Solver<')
215
CALL WARN(SolverName,'Taking default value >Adjoint<')
216
WRITE(AdjointSolName,'(A)') 'Adjoint'
217
END IF
218
ComputeDJDBeta = GetLogical( SolverParams,'Compute DJDBeta', Found)
219
IF(.NOT.Found) ComputeDJDBeta=.False.
220
ComputeDJDZs = GetLogical( SolverParams,'Compute DJDZs', Found)
221
IF(.NOT.Found) ComputeDJDZs=.False.
222
ComputeDJDZb = GetLogical( SolverParams,'Compute DJDZb', Found)
223
IF(.NOT.Found) ComputeDJDZb=.False.
224
ComputeDJDRho = GetLogical( SolverParams,'Compute DJDRho', Found)
225
IF(.NOT.Found) ComputeDJDRho=.False.
226
ComputeDJDEta = GetLogical( SolverParams,'Compute DJDEta', Found)
227
IF(.NOT.Found) ComputeDJDEta=.False.
228
229
230
! Get some constants
231
rhow = ListGetConstReal( Model % Constants, 'Water Density', UnFoundFatal=.TRUE.)
232
233
sealevel = ListGetConstReal( Model % Constants, 'Sea Level', UnFoundFatal=.TRUE. )
234
235
! Allocate
236
N = Model % MaxElementNodes
237
M = Model % Mesh % NumberOfNodes
238
IF (AllocationsDone) DEALLOCATE(FORCE, LOAD, STIFF, NodalGravity, &
239
NodalViscosity, NodalDensity, &
240
NodalZb, NodalZs, NodalGM,NodalBed, NodalU, NodalV, &
241
NodalBeta,LocalLinVelo, Nodalbetab,Nodalzsb,NodalRhob,&
242
NodalEtab,NodalZbb,&
243
NodalBetaDer,NodalEtaDer,&
244
ElementNodes % x, &
245
ElementNodes % y, ElementNodes % z )
246
247
ALLOCATE( FORCE(STDOFs*N), LOAD(N), STIFF(STDOFs*N,STDOFs*N), &
248
NodalGravity(N), NodalDensity(N), NodalViscosity(N), &
249
NodalZb(N), NodalZs(N) , NodalGM(N),NodalBed(N),&
250
NodalU(N), NodalV(N), NodalBeta(N), LocalLinVelo(N),&
251
Nodalbetab(N),NodalZsb(N), NodalRhob(N),NodalEtab(N),&
252
NodalZbb(N),&
253
NodalBetaDer(N),NodalEtaDer(N),&
254
ElementNodes % x(N), ElementNodes % y(N), ElementNodes % z(N), &
255
STAT=istat )
256
IF ( istat /= 0 ) THEN
257
CALL Fatal( SolverName, 'Memory allocation error.' )
258
END IF
259
260
AllocationsDone = .TRUE.
261
CALL INFO( SolverName, 'Memory allocation done.',Level=1 )
262
END IF
263
264
! Get Info from Direct Solver Params
265
DSolver => Model % Solvers(SolverInd)
266
! Sub - element GL parameterisation
267
SEP=GetLogical( DSolver % Values, 'Sub-Element GL parameterization',GotIt)
268
IF (.NOT.GotIt) SEP=.False.
269
IF (SEP) THEN
270
GLnIP=ListGetInteger( DSolver % Values, &
271
'GL integration points number',UnFoundFatal=.TRUE. )
272
WRITE(Message,'(a,i0,a)') 'Sub-Element GL parameterization using ',GLnIP,' IPs'
273
CALL INFO(SolverName,TRIM(Message),level=4)
274
GMSol => VariableGet( Solver % Mesh % Variables, 'GroundedMask',UnFoundFatal=.TRUE. )
275
BedrockSol => VariableGet( Solver % Mesh % Variables, 'bedrock',UnFoundFatal=.TRUE. )
276
END IF
277
278
ZbSol => VariableGet( Solver % Mesh % Variables, 'Zb', UnFoundFatal=.TRUE. )
279
Zb => ZbSol % Values
280
ZbPerm => ZbSol % Perm
281
282
ZsSol => VariableGet( Solver % Mesh % Variables, 'Zs', UnFoundFatal=.TRUE. )
283
Zs => ZsSol % Values
284
ZsPerm => ZsSol % Perm
285
286
!! SSA Solution
287
VeloSolN => VariableGet( Solver % Mesh % Variables, NeumannSolName, UnFoundFatal=.TRUE. )
288
VelocityN => VeloSolN % Values
289
VeloNPerm => VeloSolN % Perm
290
291
!! Adjoint Solution
292
VeloSolD => VariableGet( Solver % Mesh % Variables, AdjointSolName, UnFoundFatal=.TRUE. )
293
VelocityD => VeloSolD % Values
294
VeloDPerm => VeloSolD % Perm
295
296
IF (ComputeDJDBeta) Then
297
SName = GetString( SolverParams,'DJDBeta Name', Found)
298
IF(.NOT.Found) THEN
299
CALL WARN(SolverName,'Keyword >DJDBeta Name< not found in section >Solver<')
300
CALL WARN(SolverName,'Taking default value >DJDBeta<')
301
WRITE(SName,'(A)') 'DJDBeta'
302
CALL ListAddString( SolverParams, 'DJDBeta Name', TRIM(SName))
303
END IF
304
DJDBetaSol => VariableGet( Solver % Mesh % Variables, TRIM(SName) ,UnFoundFatal=.TRUE. )
305
DJDBeta => DJDBetaSol % Values
306
DJDBetaPerm => DJDBetaSol % Perm
307
308
Reset = GetLogical( SolverParams,'Reset DJDBeta', Found)
309
if (Reset.OR.(.NOT.Found)) DJDBeta = 0.0
310
End if
311
312
IF (ComputeDJDZs) Then
313
DJDZsSol => VariableGet( Solver % Mesh % Variables, 'DJDZs',UnFoundFatal=.TRUE. )
314
DJDZs => DJDZsSol % Values
315
DJDZsPerm => DJDZsSol % Perm
316
317
Reset = GetLogical( SolverParams,'Reset DJDZs', Found)
318
if (Reset.OR.(.NOT.Found)) DJDZs = 0.0
319
End if
320
IF (ComputeDJDZb) Then
321
DJDZbSol => VariableGet( Solver % Mesh % Variables, 'DJDZb', UnFoundFatal=.TRUE. )
322
DJDZb => DJDZbSol % Values
323
DJDZbPerm => DJDZbSol % Perm
324
325
Reset = GetLogical( SolverParams,'Reset DJDZb', Found)
326
if (Reset.OR.(.NOT.Found)) DJDZb = 0.0
327
End if
328
329
IF (ComputeDJDRho) Then
330
DJDRhoSol => VariableGet( Solver % Mesh % Variables, 'DJDRho', UnFoundFatal=.TRUE. )
331
DJDRho => DJDRhoSol % Values
332
DJDRhoPerm => DJDRhoSol % Perm
333
334
Reset = GetLogical( SolverParams,'Reset DJDRho', Found)
335
if (Reset.OR.(.NOT.Found)) DJDRho = 0.0
336
End if
337
IF (ComputeDJDEta) Then
338
DJDEtaSol => VariableGet( Solver % Mesh % Variables, 'DJDEta' ,UnFoundFatal=.TRUE.)
339
DJDEta => DJDEtaSol % Values
340
DJDEtaPerm => DJDEtaSol % Perm
341
342
Reset = GetLogical( SolverParams,'Reset DJDEta', Found)
343
if (Reset.OR.(.NOT.Found)) DJDEta = 0.0
344
END IF
345
346
! bulk assembly
347
DO t=1,Solver % NumberOfActiveElements
348
Element => GetActiveElement(t)
349
IF (ParEnv % myPe .NE. Element % partIndex) CYCLE
350
n = GetElementNOFNodes(Element)
351
352
NodeIndexes => Element % NodeIndexes
353
354
! set coords of highest occurring dimension to zero (to get correct path element)
355
!-------------------------------------------------------------------------------
356
ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)
357
IF (STDOFs == 1) THEN !1D SSA
358
ElementNodes % y(1:n) = 0.0_dp
359
ElementNodes % z(1:n) = 0.0_dp
360
ELSE IF (STDOFs == 2) THEN !2D SSA
361
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
362
ElementNodes % z(1:n) = 0.0_dp
363
ELSE
364
WRITE(Message,'(a,i1,a)')&
365
'It is not possible to compute SSA problems with DOFs=',&
366
STDOFs, ' . Aborting'
367
CALL Fatal( SolverName, Message)
368
STOP
369
END IF
370
371
! Read the gravity in the Body Force Section
372
BodyForce => GetBodyForce()
373
NodalGravity = 0.0_dp
374
IF ( ASSOCIATED( BodyForce ) ) THEN
375
IF (STDOFs==1) THEN
376
NodalGravity(1:n) = ListGetReal( &
377
BodyForce, 'Flow BodyForce 2', n, NodeIndexes, UnFoundFatal=.TRUE.)
378
ELSE
379
NodalGravity(1:n) = ListGetReal( &
380
BodyForce, 'Flow BodyForce 3', n, NodeIndexes, UnFoundFatal=.TRUE.)
381
END IF
382
END IF
383
384
! Read the Viscosity eta, density, and exponent m in MMaterial Section
385
! Same definition as NS Solver in Elmer - n=1/m , A = 1/ (2 eta^n)
386
Material => GetMaterial(Element)
387
cn = ListGetConstReal( Material, 'Viscosity Exponent',UnFoundFatal=.TRUE.)
388
MinSRInv = ListGetConstReal( Material, 'Critical Shear Rate',UnFoundFatal=.TRUE.)
389
390
NodalDensity=0.0_dp
391
NodalDensity(1:n) = ListGetReal( Material, 'SSA Mean Density',n,NodeIndexes,UnFoundFatal=.TRUE.)
392
393
NodalViscosity=0.0_dp
394
NodalViscosity(1:n) = ListGetReal( Material, 'SSA Mean Viscosity',n, NodeIndexes,UnFoundFatal=.TRUE.)
395
NodalEtaDer(1:n) = ListGetReal( Material, 'SSA Mean Viscosity Derivative',n, NodeIndexes,Found=HaveEtaDer)
396
397
Friction = ListGetString(Material, 'SSA Friction Law', UnFoundFatal=.TRUE.)
398
399
SELECT CASE(Friction)
400
CASE('linear')
401
iFriction = 1
402
fm = 1.0_dp
403
CASE('weertman')
404
iFriction = 2
405
CASE DEFAULT
406
CALL FATAL(SolverName,'Friction should be linear or Weertman')
407
END SELECT
408
409
410
NodalBeta(1:n) = ListGetReal( Material, 'SSA Friction Parameter',n, NodeIndexes,UnFoundFatal=.TRUE.)
411
NodalBetaDer(1:n) = ListGetReal( Material, 'SSA Friction Parameter Derivative',n, NodeIndexes,Found=HaveBetaDer)
412
IF (iFriction > 1) THEN
413
fm = ListGetConstReal( Material, 'SSA Friction Exponent', UnFoundFatal=.TRUE. )
414
415
LocalLinVelo = 0.0_dp
416
LocalLinVelo(1:n) = ListGetReal(Material, 'SSA Friction Linear Velocity', n, NodeIndexes,UnFoundFatal=.TRUE.)
417
END IF
418
419
IF (SEP) THEN
420
NodalGM(1:n)=GMSol%Values(GMSol%Perm(NodeIndexes(1:n)))
421
NodalBed(1:n)=BedrockSol%Values(BedrockSol%Perm(NodeIndexes(1:n)))
422
ENDIF
423
424
! Get the Nodal value of Zb and Zs
425
NodalZb(1:n) = Zb(ZbPerm(NodeIndexes(1:n)))
426
NodalZs(1:n) = Zs(ZsPerm(NodeIndexes(1:n)))
427
428
! Previous Velocity
429
NodalU(1:n) = VelocityN(STDOFs*(VeloNPerm(NodeIndexes(1:n))-1)+1)
430
NodalV = 0.0
431
IF (STDOFs.EQ.2) NodalV(1:n) = VelocityN(STDOFs*(VeloNPerm(NodeIndexes(1:n))-1)+2)
432
433
CALL LocalMatrixUVSSA ( STIFF, FORCE, Element, n, ElementNodes, NodalGravity, &
434
NodalDensity, NodalViscosity, NodalEtaDer,HaveEtaDer,NodalZb, NodalZs, &
435
NodalU, NodalV, NodalBeta,NodalBetaDer,HaveBetaDer,iFriction,fm,LocalLinVelo, cn, &
436
NodalGM,NodalBed,SEP,GLnIP,sealevel,rhow,&
437
MinSRInv , STDOFs,&
438
Nodalbetab,nodalzsb,nodalzbb,nodalrhob,nodaletab)
439
440
IF (ComputeDJDBeta) &
441
DJDBeta(DJDBetaPerm(NodeIndexes(1:n)))=DJDBeta(DJDBetaPerm(NodeIndexes(1:n)))+Nodalbetab(1:n)
442
IF (ComputeDJDZs) &
443
DJDZs(DJDZsPerm(NodeIndexes(1:n)))=DJDZs(DJDZsPerm(NodeIndexes(1:n)))+Nodalzsb(1:n)
444
IF (ComputeDJDZb) &
445
DJDZb(DJDZbPerm(NodeIndexes(1:n)))=DJDZb(DJDZbPerm(NodeIndexes(1:n)))+Nodalzbb(1:n)
446
IF (ComputeDJDRho) &
447
DJDRho(DJDRhoPerm(NodeIndexes(1:n)))=DJDRho(DJDRhoPerm(NodeIndexes(1:n)))+Nodalrhob(1:n)
448
IF (ComputeDJDEta) &
449
DJDEta(DJDEtaPerm(NodeIndexes(1:n)))=DJDEta(DJDEtaPerm(NodeIndexes(1:n)))+Nodaletab(1:n)
450
451
END DO
452
453
!
454
! Neumann condition
455
!
456
DO t=1,GetNOFBoundaryElements()
457
BoundaryElement => GetBoundaryElement(t)
458
459
460
IF ( .NOT. ActiveBoundaryElement(BoundaryElement,Solver) ) CYCLE
461
IF ( GetElementFamily() == 1 ) CYCLE
462
463
NodeIndexes => BoundaryElement % NodeIndexes
464
!IF (ParEnv % myPe .NE. BoundaryElement % partIndex) CYCLE
465
466
467
n = GetElementNOFNodes(BoundaryElement)
468
FORCE = 0.0e0
469
STIFF = 0.0e0
470
471
! set coords of highest occurring dimension to zero (to get correct path element)
472
!-------------------------------------------------------------------------------
473
ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)
474
IF (STDOFs == 1) THEN
475
ElementNodes % y(1:n) = 0.0_dp
476
ElementNodes % z(1:n) = 0.0_dp
477
ELSE IF (STDOFs == 2) THEN
478
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
479
ElementNodes % z(1:n) = 0.0_dp
480
ELSE
481
WRITE(Message,'(a,i1,a)')&
482
'It is not possible to compute SSA with SSA var DOFs=',&
483
STDOFs, '. Aborting'
484
CALL Fatal( SolverName, Message)
485
STOP
486
END IF
487
488
BC => GetBC()
489
IF (.NOT.ASSOCIATED( BC ) ) CYCLE
490
491
! Find the nodes for which 'Calving Front' = True
492
CalvingFront=.False.
493
CalvingFront = ListGetLogical( BC, 'Calving Front', GotIt )
494
IF (CalvingFront) THEN
495
NodalZs(1:n) = Zs(ZsPerm(NodeIndexes(1:n)))
496
NodalZb(1:n) = Zb(ZbPerm(NodeIndexes(1:n)))
497
498
! Need to access Parent Element to get Material properties
499
other_body_id = BoundaryElement % BoundaryInfo % outbody
500
IF (other_body_id < 1) THEN ! only one body in calculation
501
ParentElement => BoundaryElement % BoundaryInfo % Right
502
IF ( .NOT. ASSOCIATED(ParentElement) ) ParentElement => BoundaryElement % BoundaryInfo % Left
503
ELSE ! we are dealing with a body-body boundary and assume that the normal is pointing outwards
504
ParentElement => BoundaryElement % BoundaryInfo % Right
505
IF (ParentElement % BodyId == other_body_id) ParentElement => BoundaryElement % BoundaryInfo % Left
506
END IF
507
508
! Read Density in the Material Section
509
Material => GetMaterial(ParentElement)
510
511
NodalDensity=0.0_dp
512
NodalDensity(1:n) = ListGetReal( Material, 'SSA Mean Density',n, NodeIndexes,UnFoundFatal=.TRUE.)
513
514
! Read the gravity in the Body Force Section
515
BodyForce => GetBodyForce(ParentElement)
516
NodalGravity = 0.0_dp
517
IF ( ASSOCIATED( BodyForce ) ) THEN
518
IF (STDOFs==1) THEN
519
NodalGravity(1:n) = ListGetReal( &
520
BodyForce, 'Flow BodyForce 2', n, NodeIndexes,UnFoundFatal=.TRUE.)
521
ELSE
522
NodalGravity(1:n) = ListGetReal( &
523
BodyForce, 'Flow BodyForce 3', n, NodeIndexes,UnFoundFatal=.TRUE.)
524
END IF
525
END IF
526
527
CALL LocalMatrixBCSSA( STIFF, FORCE, BoundaryElement, n, ElementNodes,&
528
NodalDensity, NodalGravity, NodalZb, NodalZs, rhow, sealevel , &
529
nodalzsb,nodalzbb,nodalrhob)
530
531
IF (ComputeDJDZs) &
532
DJDZs(DJDZsPerm(NodeIndexes(1:n)))=DJDZs(DJDZsPerm(NodeIndexes(1:n)))+Nodalzsb(1:n)
533
IF (ComputeDJDZb) &
534
DJDZb(DJDZbPerm(NodeIndexes(1:n)))=DJDZb(DJDZbPerm(NodeIndexes(1:n)))+Nodalzbb(1:n)
535
IF (ComputeDJDRho) &
536
DJDRho(DJDRhoPerm(NodeIndexes(1:n)))=DJDRho(DJDRhoPerm(NodeIndexes(1:n)))+Nodalrhob(1:n)
537
END IF
538
END DO
539
540
RETURN
541
CONTAINS
542
543
!------------------------------------------------------------------------------
544
SUBROUTINE LocalMatrixUVSSA( STIFF, FORCE, Element, n, Nodes, gravity, &
545
Density, Viscosity,NodalEtaDer,HaveEtaDer, LocalZb, LocalZs, LocalU, &
546
LocalV, LocalBeta,NodalBetaDer,HaveBetaDer,iFriction,fm,LocalLinVelo, cm,&
547
NodalGM,NodalBed,SEP,GLnIP,sealevel,rhow,&
548
MinSRInv, STDOFs , &
549
nodalbetab,nodalzsb,nodalzbb,nodalrhob,nodaletab )
550
!------------------------------------------------------------------------------
551
REAL(KIND=dp) :: STIFF(:,:), FORCE(:), gravity(:), Density(:), &
552
Viscosity(:), LocalZb(:), LocalZs(:), &
553
LocalU(:), LocalV(:) , LocalBeta(:),LocalLinVelo(:), &
554
nodalbetab(:),nodalzbb(:),nodalzsb(:),nodalrhob(:),nodaletab(:),&
555
NodalEtaDer(:),NodalBetaDer(:)
556
LOGICAL :: HaveEtaDer,HaveBetaDer
557
INTEGER :: n, cp , STDOFs
558
INTEGER :: iFriction
559
REAL(KIND=dp) :: cm,fm
560
TYPE(Element_t), POINTER :: Element
561
LOGICAL :: Newton
562
REAL(KIND=dp) :: NodalGM(:),NodalBed(:)
563
REAL(KIND=dp) :: sealevel,rhow
564
LOGICAL :: SEP
565
INTEGER :: GLnIP
566
!------------------------------------------------------------------------------
567
REAL(KIND=dp) :: Basis(n), dBasisdx(n,3), ddBasisddx(n,3,3), detJ
568
REAL(KIND=dp) :: g, rho, eta, h, dhdx, dhdy , muder, bedrock,Hf
569
REAL(KIND=dp) :: gradS(2),gradSb(2),Slip, A(2,2), Exx, Eyy, Exy, Ezz, Ee, MinSRInv
570
REAL(KIND=dp) :: beta,Slip2,Velo(2),LinVelo,ub
571
REAL(KIND=dp) :: betab,hb,rhob,etab
572
REAL(KIND=dp) :: Id2
573
LOGICAL :: Stat, NewtonLin
574
INTEGER :: i, j, t, p, q
575
TYPE(GaussIntegrationPoints_t) :: IP
576
LOGICAL :: PartlyGroundedElement
577
578
TYPE(Nodes_t) :: Nodes
579
!------------------------------------------------------------------------------
580
581
582
nodalbetab = 0.0_dp
583
nodalzsb = 0.0_dp
584
nodalzbb = 0.0_dp
585
nodalrhob = 0.0_dp
586
nodaletab = 0.0_dp
587
588
IF (SEP) THEN
589
PartlyGroundedElement=(ANY(NodalGM(1:n).GE.0._dp).AND.ANY(NodalGM(1:n).LT.0._dp))
590
IF (PartlyGroundedElement) THEN
591
IP = GaussPoints( Element , np=GLnIP )
592
ELSE
593
IP = GaussPoints( Element )
594
ENDIF
595
ELSE
596
IP = GaussPoints( Element )
597
ENDIF
598
599
DO t=1,IP % n
600
stat = ElementInfo( Element, Nodes, IP % U(t), IP % V(t), &
601
IP % W(t), detJ, Basis, dBasisdx, ddBasisddx, .FALSE. )
602
603
! Needed Integration Point value
604
605
g = ABS(SUM( Gravity(1:n) * Basis(1:n) ))
606
rho = SUM( Density(1:n) * Basis(1:n) )
607
eta = SUM( Viscosity(1:n) * Basis(1:n) )
608
gradS = 0._dp
609
gradS(1) = SUM( LocalZs(1:n) * dBasisdx(1:n,1) )
610
if (STDOFs == 2) gradS(2) = SUM( LocalZs(1:n) * dBasisdx(1:n,2) )
611
h = SUM( (LocalZs(1:n)-LocalZb(1:n)) * Basis(1:n) )
612
beta = SUM( LocalBeta(1:n) * Basis(1:n) )
613
614
!------------------------------------------------------------------------------
615
! In the non-linear case, effective viscosity
616
Id2=1.0_dp
617
IF (cm.NE.1.0_dp) THEN
618
Exx = SUM(LocalU(1:n)*dBasisdx(1:n,1))
619
Eyy = 0.0
620
Exy = 0.0
621
IF (STDOFs.EQ.2) THEN
622
Eyy = SUM(LocalV(1:n)*dBasisdx(1:n,2))
623
Ezz = -Exx - Eyy
624
Exy = SUM(LocalU(1:n)*dBasisdx(1:n,2))
625
Exy = 0.5*(Exy + SUM(LocalV(1:n)*dBasisdx(1:n,1)))
626
Ee = 0.5*(Exx**2.0 + Eyy**2.0 + Ezz**2.0) + Exy**2.0
627
!Ee = SQRT(Ee)
628
ELSE
629
!Ee = ABS(Exx)
630
Ee = Exx * Exx
631
END IF
632
muder = eta * 0.5 * (2**cm) * ((cm-1.0)/2.0) * Ee**((cm-1.0)/2.0 - 1.0)
633
IF (sqrt(Ee) < MinSRInv) then
634
Ee = MinSRInv*MinSRInv
635
muder = 0.0_dp
636
Endif
637
Id2 = 0.5 * (2**cm) * Ee**((cm-1.0)/2.0)
638
END IF
639
640
betab = 0.0
641
hb = 0.0
642
rhob = 0.0
643
etab = 0.0
644
gradsb = 0.0
645
646
A = 0.0_dp
647
DO p=1,n
648
DO q=1,n
649
A(1,1) = 2.0*dBasisdx(q,1)*dBasisdx(p,1)
650
IF (STDOFs.EQ.2) THEN
651
A(1,1) = A(1,1) + 0.5*dBasisdx(q,2)*dBasisdx(p,2)
652
A(1,2) = dBasisdx(q,2)*dBasisdx(p,1) + &
653
0.5*dBasisdx(q,1)*dBasisdx(p,2)
654
A(2,1) = dBasisdx(q,1)*dBasisdx(p,2) + &
655
0.5*dBasisdx(q,2)*dBasisdx(p,1)
656
A(2,2) = 2.0*dBasisdx(q,2)*dBasisdx(p,2) +&
657
0.5*dBasisdx(q,1)*dBasisdx(p,1)
658
END IF
659
660
DO i=1,STDOFs
661
betab = betab + Basis(q) * Basis(p) * IP % S(t) * detJ *&
662
(- VelocityN(STDOFs*(VeloNPerm(NodeIndexes(q))-1)+i) * &
663
VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i))
664
665
DO j=1,STDOFs
666
etab = etab + 2.0 * h * Id2 * A(i,j) * IP % S(t) * detJ *&
667
(- VelocityN(STDOFs*(VeloNPerm(NodeIndexes(q))-1)+j) * &
668
VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i))
669
670
hb = hb + 2.0 * eta * Id2 * A(i,j) * IP % S(t) * detJ *&
671
(- VelocityN(STDOFs*(VeloNPerm(NodeIndexes(q))-1)+j) * &
672
VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i))
673
END DO !j
674
END DO !i
675
676
END DO !q
677
678
DO i=1,STDOFs
679
rhob = rhob - h*g*gradS(i) * IP % s(t) * detJ * Basis(p) *&
680
VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i)
681
hb = hb - rho*g*gradS(i) * IP % s(t) * detJ * Basis(p) *&
682
VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i)
683
gradsb(i) = gradsb(i) - rho * g * h * IP % s(t) * detJ * Basis(p) *&
684
VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i)
685
END DO !i
686
END DO !p
687
688
IF ((iFriction == 2).AND.(fm==1.0_dp)) iFriction=1
689
IF (iFriction > 1) THEN
690
LinVelo = SUM( LocalLinVelo(1:n) * Basis(1:n) )
691
Velo = 0.0_dp
692
Velo(1) = SUM(LocalU(1:n) * Basis(1:n))
693
IF (STDOFs == 2) Velo(2) = SUM(LocalV(1:n) * Basis(1:n))
694
ub = SQRT(Velo(1)*Velo(1)+Velo(2)*Velo(2))
695
IF (ub < LinVelo) then
696
ub = LinVelo
697
ENDIF
698
betab = betab * ub**(fm-1.0_dp)
699
END IF
700
701
IF (SEP) THEN
702
IF (ALL(NodalGM(1:n).LT.0._dp)) THEN
703
betab=0._dp
704
ELSE IF (PartlyGroundedElement) THEN
705
bedrock = SUM( NodalBed(1:n) * Basis(1:n) )
706
Hf= rhow * (sealevel-bedrock) / rho
707
if (h.lt.Hf) betab=0._dp
708
END IF
709
END IF
710
711
IF (HaveBetaDer) THEN
712
nodalbetab(1:n)=nodalbetab(1:n)+betab*Basis(1:n)*NodalBetaDer(1:n)
713
ELSE
714
nodalbetab(1:n)=nodalbetab(1:n)+betab*Basis(1:n)
715
ENDIF
716
717
nodalzbb(1:n)=nodalzbb(1:n)-hb*Basis(1:n)
718
nodalzsb(1:n)=nodalzsb(1:n)+hb*Basis(1:n)
719
Do i=1,STDOFS
720
nodalzsb(1:n)=nodalzsb(1:n)+gradsb(i)*dBasisdx(1:n,i)
721
End do
722
nodalrhob(1:n)=nodalrhob(1:n)+rhob*Basis(1:n)
723
724
IF (HaveEtaDer) THEN
725
nodaletab(1:n)=nodaletab(1:n)+etab*Basis(1:n)*NodalEtaDer(1:n)
726
ELSE
727
nodaletab(1:n)=nodaletab(1:n)+etab*Basis(1:n)
728
ENDIF
729
730
END DO !IP
731
732
!------------------------------------------------------------------------------
733
END SUBROUTINE LocalMatrixUVSSA
734
!------------------------------------------------------------------------------
735
736
!------------------------------------------------------------------------------
737
SUBROUTINE LocalMatrixBCSSA( STIFF, FORCE, Element, n, ENodes, Density, &
738
Gravity, LocalZb, LocalZs, rhow, &
739
sealevel,nodalzsb,nodalzbb,nodalrhob)
740
!------------------------------------------------------------------------------
741
TYPE(Element_t), POINTER :: Element
742
TYPE(Nodes_t) :: ENodes
743
REAL(KIND=dp) :: STIFF(:,:), FORCE(:), density(:), Gravity(:), LocalZb(:),&
744
LocalZs(:),rhow, sealevel,&
745
nodalzsb(:),nodalzbb(:),nodalrhob(:)
746
INTEGER :: n
747
!------------------------------------------------------------------------------
748
REAL(KIND=dp) :: Basis(n),dBasisdx(n,3),ddBasisddx(n,3,3), &
749
DetJ,Normal(3), rhoi, g, alpha, h, h_im,norm
750
REAL(KIND=dp) :: alphab,zsb,zbb,rhob
751
LOGICAL :: Stat
752
INTEGER :: t, i
753
TYPE(GaussIntegrationPoints_t) :: IP
754
755
!------------------------------------------------------------------------------
756
nodalzsb=0.0
757
nodalzbb=0.0
758
nodalrhob=0.0
759
760
! The front force is a concentrated nodal force in 1D-SSA and
761
! a force distributed along a line in 2D-SSA
762
763
! 1D-SSA Case : concentrated force at each nodes
764
IF (STDOFs==1) THEN !1D SSA but should be 2D problem (does elmer work in 1D?)
765
DO i = 1, n
766
g = ABS( Gravity(i) )
767
rhoi = Density(i)
768
h = LocalZs(i)-LocalZb(i)
769
h_im=max(0._dp,sealevel-LocalZb(i))
770
alpha=0.5 * g * (rhoi * h**2.0 - rhow * h_im**2.0)
771
772
alphab=VelocityD(STDOFs*(VeloDPerm(NodeIndexes(i))-1)+1)
773
nodalzsb(i)=+alphab*2.0*h*rhoi*g*0.5
774
nodalzbb(i)=-alphab*2.0*h*rhoi*g*0.5
775
if ((sealevel-LocalZb(i)).GT.0._dp) then
776
nodalzbb(i)=nodalzbb(i)+alphab*2.0*h_im*rhow*g*0.5
777
endif
778
nodalrhob(i)=alphab * 0.5 * g * h**2.0
779
END DO
780
781
! 2D-SSA Case : force distributed along the line
782
! This will work in DIM=3D only if working with Extruded Mesh and Preserve
783
! Baseline as been set to True to keep the 1D-BC
784
ELSE IF (STDOFs==2) THEN
785
786
IP = GaussPoints( Element )
787
DO t=1,IP % n
788
stat = ElementInfo( Element, ENodes, IP % U(t), IP % V(t), &
789
IP % W(t), detJ, Basis, dBasisdx, ddBasisddx, .FALSE. )
790
791
g = ABS(SUM( Gravity(1:n) * Basis(1:n) ))
792
rhoi = SUM( Density(1:n) * Basis(1:n) )
793
h = SUM( (LocalZs(1:n)-LocalZb(1:n)) * Basis(1:n))
794
h_im = max(0.0_dp , SUM( (sealevel-LocalZb(1:n)) * Basis(1:n)) )
795
alpha=0.5 * g * (rhoi * h**2.0 - rhow * h_im**2.0)
796
797
! Normal in the (x,y) plane
798
Normal = NormalVector( Element, ENodes, IP % U(t), IP % V(t), .TRUE.)
799
norm=SQRT(normal(1)**2.0+normal(2)**2.0)
800
Normal(1) = Normal(1)/norm
801
Normal(2) = Normal(2)/norm
802
803
rhob=0._dp
804
zbb=0.0_dp
805
zsb=0.0_dp
806
DO p=1,n
807
DO i=1,STDOFs
808
alphab=VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i)*&
809
Normal(i) * IP % s(t) * detJ * Basis(p)
810
rhob=rhob+alphab * 0.5 * g * h**2.0
811
zsb=zsb+alphab*2.0*h*rhoi*g*0.5
812
zbb=zbb-alphab*2.0*h*rhoi*g*0.5
813
if (SUM( (sealevel-LocalZb(1:n)) * Basis(1:n)).GT.0.0_dp) Then
814
zbb=zbb+alphab*2.0*h_im*rhow*g*0.5
815
endif
816
END DO !p
817
END DO !q
818
819
nodalrhob(1:n)=nodalrhob(1:n)+rhob*Basis(1:n)
820
nodalzsb(1:n)=nodalzsb(1:n)+zsb*Basis(1:n)
821
nodalzbb(1:n)=nodalzbb(1:n)+zbb*Basis(1:n)
822
END DO !IP
823
824
ELSE
825
826
CALL FATAL('SSASolver-SSABasalSolver','Do not work for STDOFs <> 1 or 2')
827
828
END IF
829
!------------------------------------------------------------------------------
830
END SUBROUTINE LocalMatrixBCSSA
831
832
END SUBROUTINE AdjointSSA_GradientSolver
833
834
835