Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/AdjointSSA/AdjointSSA_CostFluxDivSolver.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: f. Gillet-Chaulet (LGGE, Grenoble,France)
26
! * Email: [email protected]
27
! * Web: http://elmerice.elmerfem.org
28
! *
29
! * Original Date:
30
! *
31
! *****************************************************************************
32
SUBROUTINE AdjointSSA_CostFluxDivSolver_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_CostFluxDivSolver_init0
52
! *****************************************************************************
53
SUBROUTINE AdjointSSA_CostFluxDivSolver( Model,Solver,dt,TransientSimulation )
54
! *****************************************************************************
55
!------------------------------------------------------------------------------
56
!
57
! Compute a cost function that measure the ice flux divergence anomaly
58
! and the required forcing for the SSA adjoint problem
59
! J=int_{Pb dimension} 0.5 * (dhdt{obs} + u.grad(H) + H* div(u) - MB )**2
60
!
61
! OUTPUT are : J ; DJDu (==Velocityb variable used as forcing of the SSA adjoint problem)
62
! DJDZb (optional); DJDZs(optional)
63
!
64
! TODO : add a variance term to regularise the cost
65
!
66
! !!!!! BE careful it will reset Cost , Velocityb, and DJZb; DJDZs to 0 by default !!!!
67
! !!! If other cost and gradient are computed before ,
68
! use "<Reset Cost Value> = False" to add cost and gradient to previously computed values !!!
69
!
70
! INPUT PARAMETERS are:
71
!
72
! In solver section:
73
! Problem Dimension = Integer (default = Coordinate system dimension)
74
! Compute DJDZb = Logical (default= .True.)
75
! Compute DJDZs = Logical (default= .True.)
76
! Reset Cost Value = Logical (default = .True.)
77
! Cost Filename = File (default = 'CostOfT.dat')
78
! Cost Variable Name = String (default= 'CostValue')
79
!
80
! Variables
81
! SSAVelocity (solution of the SSA pb;DOFs== Pb Dimension)
82
! Velocityb (forcing for the adjoint pb;DOFs== Pb dimension)
83
! Zb (bottom elevation)
84
! DJDZb (gradient of J wr. to Zb, as J is fn of H=Zs-Zb)
85
! Zs (surface elevation)
86
! DJDZs (gradient of J wr. to Zs, as J is fn of H=Zs-Zb)
87
!
88
! In body Forces:
89
! Top Surface Accumulation = Real (default= 0)
90
! Bottom Surface Accumulation = Real (default = 0)
91
! Observed dhdt = Real (default = 0)
92
!
93
!******************************************************************************
94
USE DefUtils
95
IMPLICIT NONE
96
!------------------------------------------------------------------------------
97
TYPE(Solver_t) :: Solver
98
TYPE(Model_t) :: Model
99
100
REAL(KIND=dp) :: dt
101
LOGICAL :: TransientSimulation
102
!
103
CHARACTER(LEN=MAX_NAME_LEN), PARAMETER :: DefaultCostFile = 'CostOfT.dat'
104
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName,CostFile
105
CHARACTER(LEN=MAX_NAME_LEN) :: CostSolName,VarSolName
106
TYPE(Element_t),POINTER :: Element
107
TYPE(Variable_t), POINTER :: TimeVar,CostVar
108
109
TYPE(Variable_t), POINTER :: VelocitySol,VelocitybSol
110
REAL(KIND=dp), POINTER :: Velocity(:),Vb(:)
111
INTEGER, POINTER :: VeloPerm(:),VbPerm(:)
112
113
TYPE(Variable_t), POINTER :: ZbSol,ZsSol
114
TYPE(Variable_t), POINTER :: DJDZbSol,DJDZsSol
115
REAL(KIND=dp), POINTER :: Zb(:),Zs(:)
116
REAL(KIND=dp), POINTER :: DJDZb(:),DJDZs(:)
117
INTEGER, POINTER :: ZbPerm(:),ZsPerm(:)
118
INTEGER, POINTER :: DJDZbPerm(:),DJDZsPerm(:)
119
120
TYPE(ValueList_t), POINTER :: SolverParams,BodyForce
121
122
TYPE(Nodes_t) :: ElementNodes
123
124
TYPE(GaussIntegrationPoints_t) :: IntegStuff
125
126
INTEGER, POINTER :: NodeIndexes(:)
127
integer :: i,j,k,l,t,n,NMAX,DIM,ierr,c
128
129
real(kind=dp) :: Cost,Cost_S,Costb,Lambda,area
130
real(kind=dp) :: u,v,w,s,coeff,SqrtElementMetric,x
131
REAL(KIND=dp) :: Basis(Model % MaxElementNodes), dBasisdx(Model % MaxElementNodes,3)
132
REAL(KIND=dp),dimension(:),allocatable,SAVE :: NodeSMB,NodeDHDT,NodeH
133
REAL(KIND=dp),dimension(:,:),allocatable,SAVE :: Velo
134
REAL(KIND=dp) :: smb,dhdt,h,ugrdh,divu,gradh(2),Vgauss(2)
135
136
LOGICAL :: ComputeDJDZb,ComputeDJDZs,ResetCost
137
Logical :: Firsttime=.true.,Found,Parallel,stat,Gotit
138
LOGICAL :: BoundarySolver
139
CHARACTER*10 :: date,temps
140
141
save Firsttime,Parallel
142
save SolverName,CostSolName,CostFile
143
save ElementNodes
144
145
146
SolverParams => GetSolverParams()
147
148
!! check if we are on a boundary or in the bulk
149
BoundarySolver = ( Solver % ActiveElements(1) > Model % Mesh % NumberOfBulkElements )
150
IF (BoundarySolver) THEN
151
DIM = CoordinateSystemDimension() - 1
152
ELSE
153
DIM = CoordinateSystemDimension()
154
ENDIF
155
156
Lambda = GetConstReal( SolverParams,'Lambda', Found)
157
IF(.NOT.Found) THEN
158
CALL WARN(SolverName,'Keyword >Lambda< not found in section >Solver<')
159
CALL WARN(SolverName,'Taking default value Lambda=1.0')
160
Lambda = 1.0
161
End if
162
163
ComputeDJDZb = GetLogical( SolverParams,'Compute DJDZb', Found)
164
IF(.NOT.Found) ComputeDJDZb=.True.
165
ComputeDJDZs = GetLogical( SolverParams,'Compute DJDZs', Found)
166
IF(.NOT.Found) ComputeDJDZb=.True.
167
ResetCost = GetLogical( SolverParams,'Reset Cost Value', Found)
168
IF(.NOT.Found) ResetCost=.True.
169
170
171
If (Firsttime) then
172
N = model % MaxElementNodes
173
allocate(ElementNodes % x(N), ElementNodes % y(N), ElementNodes % z(N))
174
allocate(NodeSMB(N),NodeDHDT(N),Velo(2,N),NodeH(N))
175
176
!!!!!!! Check for parallel run
177
Parallel = .FALSE.
178
IF ( ASSOCIATED( Solver % Matrix % ParMatrix ) ) THEN
179
IF ( Solver % Matrix % ParMatrix % ParEnv % PEs > 1 ) THEN
180
Parallel = .TRUE.
181
END IF
182
END IF
183
184
WRITE(SolverName, '(A)') 'CostSolver_Adjoint'
185
186
!!!!!!!!!!! get Solver Variables
187
188
CostFile = ListGetString(Solver % Values,'Cost Filename',Found )
189
IF (.NOT. Found) CostFile = DefaultCostFile
190
CALL DATE_AND_TIME(date,temps)
191
If (Parallel) then
192
if (ParEnv % MyPe.EQ.0) then
193
OPEN (12, FILE=CostFile)
194
write(12,1000) date(5:6),date(7:8),date(1:4),temps(1:2),temps(3:4),temps(5:6)
195
write(12,1001) Lambda
196
write(12,'(A)') '# iter, Jdiv'
197
CLOSE(12)
198
End if
199
Else
200
OPEN (12, FILE=CostFile)
201
write(12,1000) date(5:6),date(7:8),date(1:4),temps(1:2),temps(3:4),temps(5:6)
202
write(12,1001) Lambda
203
write(12,'(A)') '# iter, Jdiv'
204
CLOSE(12)
205
End if
206
207
CostSolName = GetString( SolverParams,'Cost Variable Name', Found)
208
IF(.NOT.Found) THEN
209
CALL WARN(SolverName,'Keyword >Cost Variable Name< not found in section >Solver<')
210
CALL WARN(SolverName,'Taking default value >CostValue<')
211
WRITE(CostSolName,'(A)') 'CostValue'
212
END IF
213
214
!!! End of First visit
215
Firsttime=.false.
216
Endif
217
218
219
VelocitySol => VariableGet( Solver % Mesh % Variables, 'SSAVelocity',UnFoundFatal=.TRUE. )
220
Velocity => VelocitySol % Values
221
VeloPerm => VelocitySol % Perm
222
c=DIM ! size of the velocity variable
223
IF (VelocitySol % DOFs.NE.c) then
224
WRITE(Message,'(A,I1,A,I1)') &
225
'Variable SSAVelocity has ',VelocitySol % DOFs,' DOFs, should be',c
226
CALL FATAL(SolverName,Message)
227
End If
228
229
VelocitybSol => VariableGet( Solver % Mesh % Variables, 'Velocityb',UnFoundFatal=.TRUE. )
230
Vb => VelocitybSol % Values
231
VbPerm => VelocitybSol % Perm
232
IF (VelocitybSol % DOFs.NE.c) then
233
WRITE(Message,'(A,I1,A,I1)') &
234
'Variable Velocityb has ',VelocitybSol % DOFs,' DOFs, should be',c
235
CALL FATAL(SolverName,Message)
236
End If
237
if (ResetCost) Vb=0.0_dp
238
239
ZbSol => VariableGet( Solver % Mesh % Variables, 'Zb',UnFoundFatal=.TRUE. )
240
Zb => ZbSol % Values
241
ZbPerm => ZbSol % Perm
242
IF (ComputeDJDZb) Then
243
DJDZbSol => VariableGet( Solver % Mesh % Variables, 'DJDZb',UnFoundFatal=.TRUE. )
244
DJDZb => DJDZbSol % Values
245
DJDZbPerm => DJDZbSol % Perm
246
!!!!! Reset DJDZ to 0 HERE
247
DJDZb=0._dp
248
ENDIF
249
250
ZsSol => VariableGet( Solver % Mesh % Variables, 'Zs',UnFoundFatal=.TRUE. )
251
Zs => ZsSol % Values
252
ZsPerm => ZsSol % Perm
253
IF (ComputeDJDZs) Then
254
DJDZsSol => VariableGet( Solver % Mesh % Variables, 'DJDZs',UnFoundFatal=.TRUE. )
255
DJDZs => DJDZsSol % Values
256
DJDZsPerm => DJDZsSol % Perm
257
!!!!! Reset DJDZ to 0 HERE
258
DJDZs=0._dp
259
ENDIF
260
261
Cost=0._dp
262
area=0._dp
263
264
DO t=1,Solver % NumberOfActiveElements
265
Element => GetActiveElement(t)
266
IF (CheckPassiveElement(Element)) CYCLE
267
IF (ParEnv % myPe .NE. Element % partIndex) CYCLE
268
n = GetElementNOFNodes()
269
270
NodeIndexes => Element % NodeIndexes
271
272
! set coords of highest occurring dimension to zero (to get correct path element)
273
!-------------------------------------------------------------------------------
274
ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)
275
IF (DIM == 1) THEN !1D SSA
276
ElementNodes % y(1:n) = 0.0_dp
277
ElementNodes % z(1:n) = 0.0_dp
278
ELSE IF (DIM == 2) THEN !2D SSA
279
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
280
ElementNodes % z(1:n) = 0.0_dp
281
ELSE
282
WRITE(Message,'(a,i1,a)')&
283
'It is not possible to compute SSA problems with DOFs=',&
284
DIM, ' . Aborting'
285
CALL Fatal( SolverName, Message)
286
STOP
287
END IF
288
289
BodyForce => GetBodyForce()
290
291
! nodal values of SMB
292
NodeSMB=0.0_dp
293
NodeSMB(1:n) = ListGetReal( BodyForce, 'Top Surface Accumulation', n, NodeIndexes, GotIt)
294
IF (.NOT.GotIt) Then
295
WRITE(Message,'(A)') &
296
'No variable >Top Surface Accumulation< found in "Body Forces" default is 0'
297
CALL Info(SolverName,Message,level=6)
298
END IF
299
NodeSMB(1:n) = NodeSMB(1:n) + ListGetReal( BodyForce, 'Bottom Surface Accumulation', n, NodeIndexes, GotIt)
300
IF (.NOT.GotIt) Then
301
WRITE(Message,'(A)') &
302
'No variable >Top Surface Accumulation< found in "Body Forces" default is 0'
303
CALL Info(SolverName,Message,level=6)
304
END IF
305
306
! nodal values of observed dhdt
307
NodeDHDT=0._dp
308
NodeDHDT(1:n) = ListGetReal( BodyForce, 'Observed dhdt', n, NodeIndexes, GotIt)
309
IF (.NOT.GotIt) Then
310
WRITE(Message,'(A)') &
311
'No variable >Observed dhdt< found in "Body Forces"; default is 0'
312
CALL Info(SolverName,Message,level=6)
313
END IF
314
315
! nodal values of velocities
316
Velo=0._dp
317
Do i=1,DIM
318
Velo(i,1:n)=Velocity(DIM*(VeloPerm(NodeIndexes(1:n))-1)+i)
319
End DO
320
! get Nodal values of H
321
NodeH(1:n)=Zs(ZsPerm(NodeIndexes(1:n)))-Zb(ZbPerm(NodeIndexes(1:n)))
322
323
!------------------------------------------------------------------------------
324
! Numerical integration
325
!------------------------------------------------------------------------------
326
IntegStuff = GaussPoints( Element )
327
328
329
DO i=1,IntegStuff % n
330
U = IntegStuff % u(i)
331
V = IntegStuff % v(i)
332
W = IntegStuff % w(i)
333
!------------------------------------------------------------------------------
334
! Basis function values & derivatives at the integration point
335
!------------------------------------------------------------------------------
336
stat = ElementInfo( Element,ElementNodes,U,V,W,SqrtElementMetric, &
337
Basis,dBasisdx )
338
339
x = SUM( ElementNodes % x(1:n) * Basis(1:n) )
340
s = 1.0d0
341
342
IF ( CurrentCoordinateSystem() /= Cartesian ) THEN
343
s = 2.0d0 * PI * x
344
END IF
345
s = s * SqrtElementMetric * IntegStuff % s(i)
346
347
!get smb at IP
348
smb = SUM(NodeSMB(1:n) * Basis(1:n))
349
!observed dhdt at IP
350
dhdt = SUM(NodeDHDT(1:n) * Basis(1:n))
351
!h at IP
352
h = SUM(NodeH(1:n) * Basis(1:n))
353
354
!u.grad H
355
ugrdh=0._dp
356
Do j=1,DIM
357
gradh(j) = SUM( dBasisdx(1:n,j)*NodeH(1:n) )
358
Vgauss(j) = SUM( Basis(1:n)*(Velo(j,1:n)) )
359
ugrdh=ugrdh+gradh(j)*Vgauss(j)
360
End do
361
362
divu=0._dp
363
Do j=1,DIM
364
divu = divu + SUM( dBasisdx(1:n,j)*(Velo(j,1:n)))
365
End Do
366
367
coeff=dhdt+ugrdh+h*divu-smb
368
369
Cost=Cost+0.5*coeff*coeff*s
370
area=area+s
371
372
! compute the derivatives (NOTE Cost=Lambda*Cost at the end for output
373
! reasons)
374
Costb=0.5*s*Lambda*2.0*coeff
375
376
Do l=1,n
377
IF (ComputeDJDZb) &
378
DJDZb(DJDZbPerm(NodeIndexes(l)))=DJDZb(DJDZbPerm(NodeIndexes(l))) - & ! - car h=Zs-Zb
379
Costb*divu*Basis(l)
380
IF (ComputeDJDZs) &
381
DJDZs(DJDZsPerm(NodeIndexes(l)))=DJDZs(DJDZsPerm(NodeIndexes(l))) + & ! + car h=Zs-Zb
382
Costb*divu*Basis(l)
383
Do j=1,DIM
384
k=(VbPerm(NodeIndexes(l))-1)*c+j
385
Vb(k)=Vb(k) + Costb * Basis(l) * gradh(j) +&
386
Costb * h * dBasisdx(l,j)
387
388
IF (ComputeDJDZb) &
389
DJDZb(DJDZbPerm(NodeIndexes(l)))=DJDZb(DJDZbPerm(NodeIndexes(l))) - & ! - car h=Zs-Zb
390
Costb*Vgauss(j)*dBasisdx(l,j)
391
IF (ComputeDJDZs) &
392
DJDZs(DJDZsPerm(NodeIndexes(l)))=DJDZs(DJDZsPerm(NodeIndexes(l))) + & ! + car h=Zs-Zb
393
Costb*Vgauss(j)*dBasisdx(l,j)
394
End do !j
395
End do !l
396
397
End do !IPs
398
399
End do !elements
400
401
402
403
TimeVar => VariableGet( Solver % Mesh % Variables, 'Time' )
404
405
IF (Parallel) THEN
406
CALL MPI_ALLREDUCE(Cost,Cost_S,1,&
407
MPI_DOUBLE_PRECISION,MPI_SUM,ELMER_COMM_WORLD,ierr)
408
409
IF (Solver % Matrix % ParMatrix % ParEnv % MyPE == 0) then
410
OPEN (12, FILE=CostFile,POSITION='APPEND')
411
write(12,'(3(e13.5,2x))') TimeVar % Values(1),Cost_S,sqrt(2*Cost_S/area)
412
CLOSE(12)
413
End if
414
415
Cost_S = Lambda * Cost_S
416
417
CostVar => VariableGet( Solver % Mesh % Variables, CostSolName )
418
IF (ASSOCIATED(CostVar)) THEN
419
IF (ResetCost) then
420
CostVar % Values(1)=Cost_S
421
Else
422
CostVar % Values(1)=CostVar % Values(1)+Cost_S
423
Endif
424
END IF
425
ELSE
426
OPEN (12, FILE=CostFile,POSITION='APPEND')
427
write(12,'(3(e13.5,2x))') TimeVar % Values(1),Cost,sqrt(2*Cost/area)
428
close(12)
429
430
Cost = Lambda * Cost
431
432
CostVar => VariableGet( Solver % Mesh % Variables, CostSolName )
433
IF (ASSOCIATED(CostVar)) THEN
434
IF (ResetCost) then
435
CostVar % Values(1)=Cost
436
Else
437
CostVar % Values(1)=CostVar % Values(1)+Cost
438
Endif
439
END IF
440
END IF
441
442
Return
443
444
1000 format('#date,time,',a2,'/',a2,'/',a4,',',a2,':',a2,':',a2)
445
1001 format('#lambda,',e15.8)
446
!------------------------------------------------------------------------------
447
END SUBROUTINE AdjointSSA_CostFluxDivSolver
448
!------------------------------------------------------------------------------
449
! *****************************************************************************
450
451