Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/Adjoint/Adjoint_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 (IGE, Grenoble,France)
26
! * Email:
27
! * Web: http://elmerice.elmerfem.org
28
! *
29
! * Original Date: April 2020; Adapted from AdjointSSA_CostRegSolver
30
! *
31
! *****************************************************************************
32
SUBROUTINE Adjoint_CostRegSolver_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
CALL ListAddInteger(Solver % Values, 'Nonlinear System Norm Degree',0)
51
END SUBROUTINE Adjoint_CostRegSolver_init0
52
! *****************************************************************************
53
SUBROUTINE Adjoint_CostRegSolver( Model,Solver,dt,TransientSimulation )
54
!------------------------------------------------------------------------------
55
!******************************************************************************
56
!
57
! Compute a regularisation term and update the
58
! gradient of the cost function with respect to the regularized variable.
59
!
60
! Regularisation by default is: int_{Pb dimension} 0.5 * (d(var)/dx)**2
61
! A priori regularisation can also be used ( A priori Regularisation=True) :
62
! int_{Pb dimension} 0.5 *(1/sigma**2)*(var-var{a_priori})**2
63
!
64
! OUTPUT are : J and DJDvar
65
!
66
!
67
! !!!!! BE careful it will reset Cost and DJ to 0 by default !!!!
68
! !!! If other cost and gradient are computed before (i.e. from the adjoint pb,
69
! use "<Reset Cost Value> = False" to add cost and gradient to previously computed values !!!
70
!
71
!
72
! Required Sif parameters are:
73
!
74
! In the solver section:
75
! Cost Filename=File (default: CostOfT.dat),
76
! Optimized Variable Name= String (default='Beta'),
77
! Gradient Variable Name= String (default = 'DJDBeta'),
78
! Cost Variable Name= String (default='Cost Value'),
79
! Lambda= Real (default 1.0),
80
! Reset Cost Value= Logical (default = True),
81
! A priori Regularisation= Logical (default = .False.),
82
!
83
! In Body Force section:
84
! <VarSolName> a priori value = Real (default =0.0),
85
! <VarSolName> variance = real (default=1.0)
86
!
87
!
88
!******************************************************************************
89
USE DefUtils
90
IMPLICIT NONE
91
!------------------------------------------------------------------------------
92
TYPE(Solver_t) :: Solver
93
TYPE(Model_t) :: Model
94
95
REAL(KIND=dp) :: dt
96
LOGICAL :: TransientSimulation
97
!
98
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName='Adjoint_CostRegSolver'
99
CHARACTER(LEN=MAX_NAME_LEN), PARAMETER :: DefaultCostFile = 'CostOfT.dat'
100
CHARACTER(LEN=MAX_NAME_LEN) :: CostFile
101
CHARACTER(LEN=MAX_NAME_LEN) :: CostSolName,VarSolName,GradSolName,varname
102
103
TYPE(Variable_t), POINTER :: TimeVar,CostVar
104
105
TYPE(Variable_t), POINTER :: Variable,DJDVariable
106
REAL(KIND=dp), POINTER :: Values(:),DJDValues(:)
107
INTEGER, POINTER :: Perm(:),DJDPerm(:)
108
109
TYPE(ValueList_t), POINTER :: SolverParams,BodyForce
110
111
TYPE(Element_t),POINTER :: Element
112
TYPE(Nodes_t),SAVE :: ElementNodes
113
TYPE(GaussIntegrationPoints_t) :: IntegStuff
114
REAL(KIND=dp),ALLOCATABLE,SAVE :: Basis(:), dBasisdx(:,:)
115
INTEGER, POINTER :: NodeIndexes(:)
116
117
LOGICAL, SAVE :: Firsttime=.true.,Parallel
118
LOGICAL :: Found,stat,Gotit
119
LOGICAL :: BoundarySolver
120
integer :: i,j,k,l,t,n,NMAX,DIM,ierr,c
121
122
real(kind=dp) :: Cost,Cost_S,Lambda
123
real(kind=dp) :: Area,Area_S
124
real(kind=dp) :: u,v,w,s,coeff_reg,SqrtElementMetric,x
125
126
REAL(KIND=dp),dimension(:),allocatable,SAVE :: NodeAp,NodeRMS,NodalRegb
127
REAL(KIND=dp),dimension(:),allocatable,SAVE :: NodeValues,NodalDer,NodalGrad
128
REAL(KIND=dp) :: IPerr,IPvar
129
130
LOGICAL :: Apriori,Reset
131
LOGICAL :: HaveNodalVariable
132
LOGICAL :: HaveDer
133
134
CHARACTER*10 :: date,temps
135
136
137
SolverParams => GetSolverParams()
138
139
!! check if we are on a boundary or in the bulk
140
IF(ASSOCIATED(Solver % ActiveElements)) THEN
141
BoundarySolver = ( Solver % ActiveElements(1) > Model % Mesh % NumberOfBulkElements )
142
ELSE
143
BoundarySolver = .TRUE. ! must be true for other parts if no elements present
144
! if not boundarysolver would have active elements
145
END IF
146
147
IF (BoundarySolver) THEN
148
DIM = CoordinateSystemDimension() - 1
149
ELSE
150
DIM = CoordinateSystemDimension()
151
ENDIF
152
153
! get some needed solver parameters
154
!! Cost File for Output
155
CostFile = ListGetString(Solver % Values,'Cost Filename',Found )
156
IF (.NOT. Found) CostFile = DefaultCostFile
157
158
!! Name of the variable to regularise
159
VarSolName = ListGetString( SolverParams,'Optimized Variable Name', Found=HaveNodalVariable)
160
161
!! Name of the variable to regularise
162
GradSolName = ListGetString( SolverParams,'Gradient Variable Name', UnFoundFatal=.TRUE.)
163
!! Name of the variable with the cost function
164
CostSolName = ListGetString( SolverParams,'Cost Variable Name', Found )
165
IF(.NOT.Found) THEN
166
CALL WARN(SolverName,'Keyword >CostSolName< not found in section >Solver<')
167
CALL WARN(SolverName,'Taking default value CostValue')
168
CostSolName='CostValue'
169
End if
170
171
!! Optional weighting term
172
Lambda = GetConstReal( SolverParams,'Lambda', Found)
173
IF(.NOT.Found) THEN
174
CALL WARN(SolverName,'Keyword >Lambda< not found in section >Solver<')
175
CALL WARN(SolverName,'Taking default value Lambda=1.0')
176
Lambda = 1.0
177
End if
178
179
!! Do we need to reset cost and DJDVar to 0? Default YES
180
Reset = GetLogical( SolverParams,'Reset Cost Value', Found)
181
IF(.NOT.Found) Reset=.True.
182
183
!! What type of regularistaion ? Default penalise 1st derivative
184
Apriori = GetLogical( SolverParams,'A priori Regularisation', Found)
185
IF(.NOT.Found) Apriori=.False.
186
187
!!! SOME INITIALISATION AT FIRST TIME
188
If (Firsttime) then
189
N = model % MaxElementNodes
190
allocate(ElementNodes % x(N), ElementNodes % y(N), ElementNodes % z(N))
191
allocate(Basis(N),dBasisdx(N,3))
192
allocate(NodeAp(N),NodeRMS(N),NodeValues(N),NodalRegb(N),NodalDer(N),NodalGrad(N))
193
194
!!!!!!! Check for parallel run
195
!Parallel = .FALSE.
196
!IF ( ASSOCIATED( Solver % Matrix % ParMatrix ) ) THEN
197
! IF ( Solver % Matrix % ParMatrix % ParEnv % PEs > 1 ) THEN
198
! Parallel = .TRUE.
199
! END IF
200
!END IF
201
Parallel = ParEnv % PEs > 1
202
203
!!!!!!!!!!! initiate Cost File
204
205
CALL DATE_AND_TIME(date,temps)
206
If (Parallel) then
207
if (ParEnv % MyPe.EQ.0) then
208
OPEN (12, FILE=CostFile)
209
write(12,1000) date(5:6),date(7:8),date(1:4),temps(1:2),temps(3:4),temps(5:6)
210
write(12,1001) Lambda
211
write(12,'(A)') '# iter, Jreg,sqrt(2*Jreg/area)'
212
CLOSE(12)
213
End if
214
Else
215
OPEN (12, FILE=CostFile)
216
write(12,1000) date(5:6),date(7:8),date(1:4),temps(1:2),temps(3:4),temps(5:6)
217
write(12,1001) Lambda
218
write(12,'(A)') '# iter, Jreg,sqrt(2*Jreg/area)'
219
CLOSE(12)
220
End if
221
222
!!! End of First visit
223
Firsttime=.false.
224
Endif
225
!!!! INITIALISATION DONE
226
IF (HaveNodalVariable) THEN
227
Variable => VariableGet( Solver % Mesh % Variables, VarSolName , UnFoundFatal=.TRUE.)
228
Values => Variable % Values
229
Perm => Variable % Perm
230
END IF
231
232
DJDVariable => VariableGet( Solver % Mesh % Variables, GradSolName , UnFoundFatal=.TRUE. )
233
DJDValues => DJDVariable % Values
234
DJDPerm => DJDVariable % Perm
235
IF (Reset) DJDValues=0.0_dp
236
237
Cost=0._dp
238
Area=0._dp
239
240
DO t=1,Solver % NumberOfActiveElements
241
Element => GetActiveElement(t)
242
IF (CheckPassiveElement(Element)) THEN
243
CYCLE
244
END IF
245
BodyForce => GetBodyForce(Element)
246
IF (.NOT.ASSOCIATED(BodyForce)) THEN
247
IF (Apriori.OR.(.NOT.HaveNodalVariable)) &
248
CALL FATAL(SolverName,'Body force should be associated for this regularisation')
249
ENDIF
250
251
n = GetElementNOFNodes()
252
253
NodeIndexes => Element % NodeIndexes
254
255
! set coords of highest occurring dimension to zero (to get correct path element)
256
!-------------------------------------------------------------------------------
257
ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)
258
SELECT CASE (DIM)
259
CASE (1)
260
ElementNodes % y(1:n) = 0.0_dp
261
ElementNodes % z(1:n) = 0.0_dp
262
CASE (2)
263
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
264
ElementNodes % z(1:n) = 0.0_dp
265
CASE (3)
266
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
267
ElementNodes % z(1:n) = Solver % Mesh % Nodes % z(NodeIndexes)
268
END SELECT
269
270
! Compute integrated cost
271
IF (Apriori) then
272
NodeAp(1:n) = ListGetReal( BodyForce, 'CostReg Nodal Prior', n, NodeIndexes, GotIt)
273
IF (.NOT.GotIt) Then
274
CALL WARN(SolverName,'No value for the prior found in <Body Force>, default is 0')
275
NodeAp(1:n) = 0._dp
276
END IF
277
NodeRMS(1:n)=ListGetReal( BodyForce,'CostReg Nodal std', n, NodeIndexes, GotIt)
278
IF (.NOT.GotIt) Then
279
CALL WARN(SolverName,'No value for the standard deviation found in <Body Force>, default is 1')
280
NodeRMS=1.0_dp
281
END IF
282
END IF
283
284
! Nodal values of the variable
285
IF (HaveNodalVariable) THEN
286
NodeValues(1:n)=Values(Perm(NodeIndexes(1:n)))
287
HaveDer=.FALSE.
288
ELSE
289
NodeValues(1:n)=ListGetReal( BodyForce,'CostReg Nodal Variable',n, NodeIndexes, UnFoundFatal=.TRUE.)
290
NodalDer(1:n) = ListGetReal( BodyForce,'CostReg Nodal Variable derivative',n,NodeIndexes,Found=HaveDer)
291
END IF
292
293
!------------------------------------------------------------------------------
294
! Numerical integration
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
319
320
IF (Apriori) then
321
IPerr = SUM((NodeValues(1:n)-NodeAp(1:n))*Basis(1:n))
322
IPvar = SUM(NodeRMS(1:n)*Basis(1:n))
323
coeff_reg=IPerr/IPvar
324
coeff_reg = 0.5*coeff_reg*coeff_reg
325
326
IF (HaveDer) THEN
327
NodalGrad(1:n)=Basis(1:n)*NodalDer(1:n)
328
ELSE
329
NodalGrad(1:n)=Basis(1:n)
330
ENDIF
331
332
!Now compute the derivative
333
NodalRegb(1:n)=NodalRegb(1:n)+&
334
s*Lambda*IPerr*NodalGrad(1:n)/(IPVar**2.0)
335
Else
336
coeff_reg=0._dp
337
DO k=1,DIM
338
coeff_reg = coeff_reg + 0.5*SUM(NodeValues(1:n) * dBasisdx(1:n,k))**2
339
END DO
340
341
!Now compute the derivative
342
DO k=1,DIM
343
344
IF (HaveDer) THEN
345
NodalGrad(1:n)=dBasisdx(1:n,k)*NodalDer(1:n)
346
ELSE
347
NodalGrad(1:n)=dBasisdx(1:n,k)
348
ENDIF
349
350
NodalRegb(1:n)=NodalRegb(1:n)+&
351
s*Lambda*(SUM(dBasisdx(1:n,k)*NodeValues(1:n))*NodalGrad(1:n))
352
END DO
353
Endif
354
355
Cost=Cost+coeff_reg*s
356
Area=Area+s
357
358
End do !IP
359
360
DJDValues(DJDPerm(NodeIndexes(1:n)))=DJDValues(DJDPerm(NodeIndexes(1:n))) + NodalRegb(1:n)
361
362
End do !Elements
363
364
TimeVar => VariableGet( Solver % Mesh % Variables, 'Time' )
365
366
IF (Parallel) THEN
367
CALL MPI_ALLREDUCE(Cost,Cost_S,1,&
368
MPI_DOUBLE_PRECISION,MPI_SUM,ELMER_COMM_WORLD,ierr)
369
CALL MPI_ALLREDUCE(Area,Area_S,1,&
370
MPI_DOUBLE_PRECISION,MPI_SUM,ELMER_COMM_WORLD,ierr)
371
CostVar => VariableGet( Solver % Mesh % Variables, CostSolName )
372
IF (ASSOCIATED(CostVar)) THEN
373
IF (Reset) then
374
CostVar % Values(1)=Lambda*Cost_S
375
Else
376
CostVar % Values(1)=CostVar % Values(1)+Lambda*Cost_S
377
Endif
378
END IF
379
IF (ParEnv % MyPE == 0) then
380
OPEN (12, FILE=CostFile,POSITION='APPEND')
381
write(12,'(3(ES20.11E3))') TimeVar % Values(1),Cost_S,sqrt(2*Cost_S/Area_S)
382
CLOSE(12)
383
End if
384
ELSE
385
CostVar => VariableGet( Solver % Mesh % Variables, CostSolName )
386
IF (ASSOCIATED(CostVar)) THEN
387
IF (Reset) then
388
CostVar % Values(1)=Lambda*Cost
389
Else
390
CostVar % Values(1)=CostVar % Values(1)+Lambda*Cost
391
Endif
392
END IF
393
OPEN (12, FILE=CostFile,POSITION='APPEND')
394
write(12,'(3(ES20.11E3))') TimeVar % Values(1),Cost,sqrt(2*Cost/Area)
395
close(12)
396
Cost_S=Cost
397
END IF
398
399
Solver % Variable % Values(1)=Cost_S
400
401
Return
402
403
1000 format('#date,time,',a2,'/',a2,'/',a4,',',a2,':',a2,':',a2)
404
1001 format('#lambda,',e15.8)
405
!------------------------------------------------------------------------------
406
END SUBROUTINE Adjoint_CostRegSolver
407
!------------------------------------------------------------------------------
408
! *****************************************************************************
409
410