Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/AdjointSSA/AdjointSSA_CostRegSolver.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
! *****************************************************************************
33
SUBROUTINE AdjointSSA_CostRegSolver( Model,Solver,dt,TransientSimulation )
34
!------------------------------------------------------------------------------
35
!******************************************************************************
36
!
37
! Compute a regularisation term for SSA inverse problems and update the
38
! gradient of the cost function with respect to the regularized variable.
39
!
40
! Regularisation by default is: int_{Pb dimension} 0.5 * (d(var)/dx)**2
41
! A priori regularisation can also be used ( A priori Regularisation=True) :
42
! int_{Pb dimension} 0.5 *(1/sigma**2)*(var-var{a_priori})**2
43
!
44
! OUTPUT are : J and DJDvar
45
!
46
!
47
! !!!!! BE careful it will reset Cost and DJ to 0 by default !!!!
48
! !!! If other cost and gradient are computed before (i.e. from the adjoint pb,
49
! use "<Reset Cost Value> = False" to add cost and gradient to previously computed values !!!
50
!
51
!
52
! Required Sif parameters are:
53
!
54
! In the solver section:
55
! Problem Dimension=Integer (default:coordinate system dimension),
56
! Cost Filename=File (default: CostOfT.dat),
57
! Optimized Variable Name= String (default='Beta'),
58
! Gradient Variable Name= String (default = 'DJDBeta'),
59
! Cost Variable Name= String (default='Cost Value'),
60
! Lambda= Real (default 1.0),
61
! Reset Cost Value= Logical (default = True),
62
! A priori Regularisation= Logical (default = .False.),
63
!
64
! In Body Force section:
65
! <VarSolName> a priori value = Real (default =0.0),
66
! <VarSolName> variance = real (default=1.0)
67
!
68
!
69
!******************************************************************************
70
USE DefUtils
71
IMPLICIT NONE
72
!------------------------------------------------------------------------------
73
TYPE(Solver_t) :: Solver
74
TYPE(Model_t) :: Model
75
76
REAL(KIND=dp) :: dt
77
LOGICAL :: TransientSimulation
78
!
79
CHARACTER(LEN=MAX_NAME_LEN), PARAMETER :: DefaultCostFile = 'CostOfT.dat'
80
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName,CostFile
81
CHARACTER(LEN=MAX_NAME_LEN) :: CostSolName,VarSolName,GradSolName,varname
82
TYPE(Element_t),POINTER :: Element
83
TYPE(Variable_t), POINTER :: TimeVar,CostVar
84
85
TYPE(Variable_t), POINTER :: Variable,DJDVariable
86
REAL(KIND=dp), POINTER :: Values(:),DJDValues(:)
87
INTEGER, POINTER :: Perm(:),DJDPerm(:)
88
89
TYPE(ValueList_t), POINTER :: SolverParams,BodyForce
90
TYPE(Nodes_t) :: ElementNodes
91
TYPE(GaussIntegrationPoints_t) :: IntegStuff
92
INTEGER, POINTER :: NodeIndexes(:)
93
94
Logical :: Firsttime=.true.,Found,Parallel,stat,Gotit
95
integer :: i,j,k,l,t,n,NMAX,DIM,ierr,c
96
97
real(kind=dp) :: Cost,Cost_S,Lambda
98
real(kind=dp) :: u,v,w,s,coeff_reg,SqrtElementMetric,x
99
100
REAL(KIND=dp),dimension(:),allocatable,SAVE :: NodeAp,NodeRMS,NodeValues,NodalRegb
101
REAL(KIND=dp) :: Basis(Model % MaxElementNodes), dBasisdx(Model % MaxElementNodes,3)
102
REAL(KIND=dp) :: IPerr,IPvar
103
104
LOGICAL :: Apriori,Reset
105
106
CHARACTER*10 :: date,temps
107
108
save Firsttime,Parallel
109
save SolverName,CostSolName,VarSolName,Lambda,CostFile
110
save ElementNodes
111
112
WRITE(SolverName, '(A)') 'CostSolver_Regular'
113
114
CALL Info(SolverName,'***********************',level=0)
115
CALL Info(SolverName,' This solver has been replaced by:',level=0)
116
CALL Info(SolverName,' Adjoint_CostRegSolver ',level=0)
117
CALL Info(SolverName,' See documentation under: ',level=0)
118
CALL Info(SolverName,' elmerice/Solvers/Documentation ',level=0)
119
CALL Info(SolverName,'***********************',level=0)
120
CALL FATAL(SolverName,' Use new solver !!')
121
122
SolverParams => GetSolverParams()
123
124
!! Dimension of the pb; ie with SSA we can be 1D or 2D on a 2D mesh, or 2D on a 3D mesh
125
DIM=GetInteger(SolverParams ,'Problem Dimension',Found)
126
If (.NOT.Found) then
127
CALL WARN(SolverName,'Keyword >Problem Dimension< not found, assume DIM = CoordinateSystemDimension()')
128
DIM = CoordinateSystemDimension()
129
Endif
130
131
! get some needed solver parameters
132
!! Cost File for Output
133
CostFile = ListGetString(Solver % Values,'Cost Filename',Found )
134
IF (.NOT. Found) CostFile = DefaultCostFile
135
136
!! Name of the variable to regularise
137
VarSolName = GetString( SolverParams,'Optimized Variable Name', Found)
138
IF(.NOT.Found) THEN
139
CALL WARN(SolverName,'Keyword >Optimized Variable Name< not found in section >Solver<')
140
CALL WARN(SolverName,'Taking default value >Beta<')
141
WRITE(VarSolName,'(A)') 'Beta'
142
END IF
143
144
!! Name of the variable to regularise
145
GradSolName = GetString( SolverParams,'Gradient Variable Name', Found)
146
IF(.NOT.Found) THEN
147
CALL WARN(SolverName,'Keyword >Optimized Variable Name< not found in section >Solver<')
148
CALL WARN(SolverName,'Taking default value >DJDBeta<')
149
WRITE(GradSolName,'(A)') 'DJDBeta'
150
END IF
151
152
153
!! Name of the variable with the cost function
154
CostSolName = GetString( SolverParams,'Cost Variable Name', Found)
155
IF(.NOT.Found) THEN
156
CALL WARN(SolverName,'Keyword >Cost Variable Name< not found in section >Solver<')
157
CALL WARN(SolverName,'Taking default value >CostValue<')
158
WRITE(CostSolName,'(A)') 'CostValue'
159
END IF
160
161
!! Optional weighting term
162
Lambda = GetConstReal( SolverParams,'Lambda', Found)
163
IF(.NOT.Found) THEN
164
CALL WARN(SolverName,'Keyword >Lambda< not found in section >Solver<')
165
CALL WARN(SolverName,'Taking default value Lambda=1.0')
166
Lambda = 1.0
167
End if
168
169
!! Do we need to reset cost and DJDVar to 0? Default YES
170
Reset = GetLogical( SolverParams,'Reset Cost Value', Found)
171
IF(.NOT.Found) Reset=.True.
172
173
!! What type of regularistaion ? Default penalise 1st derivative
174
Apriori = GetLogical( SolverParams,'A priori Regularisation', Found)
175
IF(.NOT.Found) Apriori=.False.
176
177
!!! SOME INITIALISATION AT FIRST TIME
178
If (Firsttime) then
179
N = model % MaxElementNodes
180
allocate(ElementNodes % x(N), ElementNodes % y(N), ElementNodes % z(N))
181
allocate(NodeAp(N),NodeRMS(N),NodeValues(N),NodalRegb(N))
182
183
!!!!!!! Check for parallel run
184
Parallel = .FALSE.
185
IF ( ASSOCIATED( Solver % Matrix % ParMatrix ) ) THEN
186
IF ( Solver % Matrix % ParMatrix % ParEnv % PEs > 1 ) THEN
187
Parallel = .TRUE.
188
END IF
189
END IF
190
191
!!!!!!!!!!! initiate Cost File
192
193
CALL DATE_AND_TIME(date,temps)
194
If (Parallel) then
195
if (ParEnv % MyPe.EQ.0) then
196
OPEN (12, FILE=CostFile)
197
write(12,1000) date(5:6),date(7:8),date(1:4),temps(1:2),temps(3:4),temps(5:6)
198
write(12,1001) Lambda
199
write(12,'(A)') '# iter, Jreg'
200
CLOSE(12)
201
End if
202
Else
203
OPEN (12, FILE=CostFile)
204
write(12,1000) date(5:6),date(7:8),date(1:4),temps(1:2),temps(3:4),temps(5:6)
205
write(12,1001) Lambda
206
write(12,'(A)') '# iter, Jreg'
207
CLOSE(12)
208
End if
209
210
!!! End of First visit
211
Firsttime=.false.
212
Endif
213
!!!! INITIALISATION DONE
214
215
Variable => VariableGet( Solver % Mesh % Variables, VarSolName )
216
IF ( ASSOCIATED( Variable ) ) THEN
217
Values => Variable % Values
218
Perm => Variable % Perm
219
ELSE
220
WRITE(Message,'(A,A,A)') &
221
'No variable >',VarSolName,' < found'
222
CALL FATAL(SolverName,Message)
223
END IF
224
DJDVariable => VariableGet( Solver % Mesh % Variables, GradSolName )
225
IF ( ASSOCIATED( DJDVariable ) ) THEN
226
DJDValues => DJDVariable % Values
227
DJDPerm => DJDVariable % Perm
228
ELSE
229
WRITE(Message,'(A,A,A)') &
230
'No variable >',VarSolName,' < found'
231
CALL FATAL(SolverName,Message)
232
END IF
233
IF (Reset) DJDValues=0.0_dp
234
235
236
Cost=0._dp
237
238
DO t=1,Solver % NumberOfActiveElements
239
Element => GetActiveElement(t)
240
IF (CheckPassiveElement(Element)) THEN
241
!PRINT *,ParEnv%myPe,'REG: PASSIVE ELEEMNT'
242
CYCLE
243
END IF
244
IF (ParEnv % myPe .NE. Element % partIndex) CYCLE
245
n = GetElementNOFNodes()
246
247
NodeIndexes => Element % NodeIndexes
248
249
! set coords of highest occurring dimension to zero (to get correct path element)
250
!-------------------------------------------------------------------------------
251
ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)
252
IF (DIM == 1) THEN !1D SSA
253
ElementNodes % y(1:n) = 0.0_dp
254
ElementNodes % z(1:n) = 0.0_dp
255
ELSE IF (DIM == 2) THEN !2D SSA
256
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
257
ElementNodes % z(1:n) = 0.0_dp
258
ELSE
259
WRITE(Message,'(a,i1,a)')&
260
'It is not possible to compute SSA problems with DOFs=',&
261
DIM, ' . Aborting'
262
CALL Fatal( SolverName, Message)
263
STOP
264
END IF
265
266
! Compute inetgrated cost
267
268
269
IF (Apriori) then
270
BodyForce => GetBodyForce()
271
write(varname,'(A,A)') trim(VarSolName),' a priori value'
272
NodeAp(1:n) = 0._dp
273
NodeAp(1:n) = ListGetReal( BodyForce, trim(varname), n, NodeIndexes, GotIt)
274
IF (.NOT.GotIt) Then
275
WRITE(Message,'(A,A,A)') &
276
'No variable >',trim(varname),'< found in "Body Forces" default is 0'
277
CALL Info(SolverName,Message,level=6)
278
END IF
279
write(varname,'(A,A)') trim(VarSolName),' variance'
280
NodeRMS(1:n)=ListGetReal( BodyForce, trim(varname), n, NodeIndexes, GotIt)
281
IF (.NOT.GotIt) Then
282
WRITE(Message,'(A,A,A)') &
283
'No variable >',trim(varname),'< found in "Body Forces" default is 1'
284
CALL Info(SolverName,Message,level=6)
285
NodeRMS=1.0_dp
286
END IF
287
END IF
288
289
! Nodal values of the variable
290
NodeValues(1:n)=Values(Perm(NodeIndexes(1:n)))
291
292
!------------------------------------------------------------------------------
293
! Numerical integration
294
!------------------------------------------------------------------------------
295
296
NodalRegb = 0.0_dp
297
298
IntegStuff = GaussPoints( Element )
299
300
DO i=1,IntegStuff % n
301
U = IntegStuff % u(i)
302
V = IntegStuff % v(i)
303
W = IntegStuff % w(i)
304
!------------------------------------------------------------------------------
305
! Basis function values & derivatives at the integration point
306
!------------------------------------------------------------------------------
307
stat = ElementInfo( Element,ElementNodes,U,V,W,SqrtElementMetric, &
308
Basis,dBasisdx )
309
310
x = SUM( ElementNodes % x(1:n) * Basis(1:n) )
311
s = 1.0d0
312
313
IF ( CurrentCoordinateSystem() /= Cartesian ) THEN
314
s = 2.0d0 * PI * x
315
END IF
316
s = s * SqrtElementMetric * IntegStuff % s(i)
317
318
IF (Apriori) then
319
IPerr = SUM((NodeValues(1:n)-NodeAp(1:n))*Basis(1:n))
320
IPvar = SUM(NodeRMS(1:n)*Basis(1:n))
321
coeff_reg=IPerr/IPvar
322
coeff_reg = coeff_reg*coeff_reg
323
324
!Now compute the derivative
325
NodalRegb(1:n)=NodalRegb(1:n)+&
326
s*Lambda*IPerr*Basis(1:n)/(IPVar**2.0)
327
Else
328
coeff_reg = SUM(NodeValues(1:n) * dBasisdx(1:n,1))
329
coeff_reg = coeff_reg*coeff_reg
330
IF (DIM.eq.2) then
331
coeff_reg=coeff_reg+ &
332
SUM(NodeValues(1:n)*dBasisdx(1:n,2))*SUM(NodeValues(1:n) * dBasisdx(1:n,2))
333
END IF
334
335
!Now compute the derivative
336
NodalRegb(1:n)=NodalRegb(1:n)+&
337
s*Lambda*(SUM(dBasisdx(1:n,1)*NodeValues(1:n))*dBasisdx(1:n,1))
338
IF (DIM.eq.2) then
339
NodalRegb(1:n)=NodalRegb(1:n)+&
340
s*Lambda*(SUM(dBasisdx(1:n,2)*NodeValues(1:n))*dBasisdx(1:n,2))
341
End if
342
Endif
343
344
345
Cost=Cost+0.5*coeff_reg*s
346
347
End do !IP
348
349
DJDValues(DJDPerm(NodeIndexes(1:n)))=DJDValues(DJDPerm(NodeIndexes(1:n))) + NodalRegb(1:n)
350
351
End do !Elements
352
353
TimeVar => VariableGet( Solver % Mesh % Variables, 'Time' )
354
355
IF (Parallel) THEN
356
CALL MPI_ALLREDUCE(Cost,Cost_S,1,&
357
MPI_DOUBLE_PRECISION,MPI_SUM,ELMER_COMM_WORLD,ierr)
358
CostVar => VariableGet( Solver % Mesh % Variables, CostSolName )
359
IF (ASSOCIATED(CostVar)) THEN
360
IF (Reset) then
361
CostVar % Values(1)=Lambda*Cost_S
362
Else
363
CostVar % Values(1)=CostVar % Values(1)+Lambda*Cost_S
364
Endif
365
END IF
366
IF (Solver % Matrix % ParMatrix % ParEnv % MyPE == 0) then
367
OPEN (12, FILE=CostFile,POSITION='APPEND')
368
write(12,'(e13.5,2x,e15.8)') TimeVar % Values(1),Cost_S
369
CLOSE(12)
370
End if
371
ELSE
372
CostVar => VariableGet( Solver % Mesh % Variables, CostSolName )
373
IF (ASSOCIATED(CostVar)) THEN
374
IF (Reset) then
375
CostVar % Values(1)=Lambda*Cost
376
Else
377
CostVar % Values(1)=CostVar % Values(1)+Lambda*Cost
378
Endif
379
END IF
380
OPEN (12, FILE=CostFile,POSITION='APPEND')
381
write(12,'(e13.5,2x,e15.8)') TimeVar % Values(1),Cost
382
close(12)
383
END IF
384
385
Return
386
387
1000 format('#date,time,',a2,'/',a2,'/',a4,',',a2,':',a2,':',a2)
388
1001 format('#lambda,',e15.8)
389
!------------------------------------------------------------------------------
390
END SUBROUTINE AdjointSSA_CostRegSolver
391
!------------------------------------------------------------------------------
392
! *****************************************************************************
393
394