Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Tests/InvMeth_AdjRobin/PROG/GradientValidation.f90
3206 views
1
! Compare the total derivative of the cost function computed as:
2
! (1) dJ=P.G where P is a perturbation vector of the variable of interest
3
! G is the gradient of the cost function computed by an inverse method
4
! (2) [J(V+hP)-J(V)]/h : forward finite difference computation of the derivative
5
! V is the variable of interest
6
! h is the step size
7
!
8
!
9
! Compute (1) from at the first iteration and update V=Vini+hP, h=1
10
! Compute (2) for all the other iteration with h^i+1=h^i/2
11
!
12
! Serial/parallel 2D/3D
13
!
14
! Keyword in Solver section of the .sif:
15
! Cost Variable Name
16
! Optimized Variable Name
17
! Perturbed Variable Name
18
! Gradient Variable Name
19
! Result File
20
!
21
! Output: in result File: h , abs((1)-(2))/(1) , (1), (2)
22
!
23
!
24
! *****************************************************************************
25
SUBROUTINE GradientValidation ( Model,Solver,dt,TransientSimulation )
26
!------------------------------------------------------------------------------
27
!******************************************************************************
28
USE DefUtils
29
IMPLICIT NONE
30
!------------------------------------------------------------------------------
31
TYPE(Solver_t) :: Solver
32
TYPE(Model_t) :: Model
33
34
REAL(KIND=dp) :: dt
35
LOGICAL :: TransientSimulation
36
!
37
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName
38
TYPE(Element_t),POINTER :: Element
39
TYPE(ValueList_t), POINTER :: SolverParams
40
TYPE(Variable_t), POINTER :: Var,PVar,CostVar,GradVar
41
REAL(KIND=dp), POINTER :: Values(:),PValues(:),CostValues(:),GradValues(:)
42
INTEGER, POINTER :: Perm(:),PPerm(:),GradPerm(:)
43
INTEGER, POINTER :: NodeIndexes(:)
44
45
REAL(KIND=dp),allocatable :: x(:),xp(:),g(:)
46
REAL(KIND=dp) :: J,J0,h,dJ,dJd
47
48
integer :: i,t,n,NMAX,NActiveNodes
49
integer :: ierr
50
integer,allocatable :: ActiveNodes(:)
51
integer,allocatable :: NewNode(:)
52
integer,parameter :: io=20
53
integer :: MyPe=-1
54
55
Logical :: FirstVisit=.true.,Found, UnFoundFatal
56
Logical :: Parallel
57
logical,allocatable :: VisitedNode(:)
58
59
CHARACTER(LEN=MAX_NAME_LEN) :: CostSolName,VarSolName,GradSolName,PSolName,ResultFile
60
CHARACTER*10 :: date,temps
61
62
!
63
save FirstVisit
64
save SolverName
65
save CostSolName,VarSolName,GradSolName,ResultFile
66
save ActiveNodes,NActiveNodes
67
save x,xp
68
save J0,h,dJ
69
save MyPe
70
save Parallel
71
72
73
! Read Constant from sif solver section
74
IF(FirstVisit) Then
75
76
WRITE(SolverName, '(A)') 'GradientValidation'
77
78
! Check we have a parallel run
79
Parallel = .FALSE.
80
IF(ASSOCIATED(Solver % Matrix % ParMatrix)) Then
81
IF ( Solver % Matrix % ParMatrix % ParEnv % PEs > 1 ) Parallel =.True.
82
MyPe=ParEnv % MyPe
83
End if
84
85
86
SolverParams => GetSolverParams()
87
88
!!!!!!!!!!!!find active nodes
89
NMAX=Solver % Mesh % NumberOfNodes
90
allocate(VisitedNode(NMAX),NewNode(NMAX))
91
VisitedNode=.false.
92
NewNode=-1
93
94
NActiveNodes=0
95
DO t=1,Solver % NumberOfActiveElements
96
Element => GetActiveElement(t)
97
n = GetElementNOFNodes()
98
NodeIndexes => Element % NodeIndexes
99
Do i=1,n
100
if (VisitedNode(NodeIndexes(i))) then
101
cycle
102
else
103
VisitedNode(NodeIndexes(i))=.true.
104
NActiveNodes=NActiveNodes+1
105
NewNode(NActiveNodes)=NodeIndexes(i)
106
endif
107
End do
108
End do
109
110
if (NActiveNodes.eq.0) THEN
111
WRITE(Message,'(A)') 'NActiveNodes = 0 !!!'
112
CALL FATAL(SolverName,Message)
113
End if
114
115
allocate(ActiveNodes(NActiveNodes),x(NActiveNodes),xp(NActiveNodes),g(NActiveNodes))
116
ActiveNodes(1:NActiveNodes)=NewNode(1:NActiveNodes)
117
118
deallocate(VisitedNode,NewNode)
119
120
!!!!!!! Solver Params
121
122
CostSolName = GetString( SolverParams,'Cost Variable Name', Found)
123
IF(.NOT.Found) THEN
124
CALL WARN(SolverName,'Keyword >Cost Variable Name< not found in section >Solver<')
125
CALL WARN(SolverName,'Taking default value >CostValue<')
126
WRITE(CostSolName,'(A)') 'CostValue'
127
END IF
128
VarSolName = GetString( SolverParams,'Optimized Variable Name', Found)
129
IF(.NOT.Found) THEN
130
CALL WARN(SolverName,'Keyword >Optimized Variable Name< not found in section >Solver<')
131
CALL WARN(SolverName,'Taking default value >Beta<')
132
WRITE(VarSolName,'(A)') 'Beta'
133
END IF
134
PSolName = GetString( SolverParams,'Perturbed Variable Name', Found)
135
IF(.NOT.Found) THEN
136
CALL WARN(SolverName,'Keyword >Perturbed Variable Name< not found in section >Solver<')
137
CALL WARN(SolverName,'Taking default value >BetaP<')
138
WRITE(VarSolName,'(A)') 'BetaP'
139
END IF
140
GradSolName = GetString( SolverParams,'Gradient Variable Name', Found)
141
IF(.NOT.Found) THEN
142
CALL WARN(SolverName,'Keyword >Gradient Variable Name< not found in section >Solver<')
143
CALL WARN(SolverName,'Taking default value >DJDB<')
144
WRITE(GradSolName,'(A)') 'DJDB'
145
END IF
146
ResultFile=GetString( SolverParams,'Result File',Found)
147
IF(Found) Then
148
IF ((Parallel.AND.(MyPe.EQ.0)).OR.(.NOT.Parallel)) Then
149
open(io,file=trim(ResultFile))
150
CALL DATE_AND_TIME(date,temps)
151
write(io,'(a1,a2,a1,a2,a1,a4,5x,a2,a1,a2,a1,a2)')'#',date(5:6),'/',date(7:8),'/',date(1:4), &
152
temps(1:2),':',temps(3:4),':',temps(5:6)
153
write(io,'(A)') '# step size, relative error, Adjoint total der., FD total der.'
154
close(io)
155
ENDIF
156
ELSE
157
CALL FATAL(SolverName,'Keyword <Result File> Not Found')
158
ENDIF
159
160
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
161
CostVar => VariableGet( Solver % Mesh % Variables, CostSolName,UnFoundFatal=UnFoundFatal)
162
CostValues => CostVar % Values
163
164
Var => VariableGet( Solver % Mesh % Variables, VarSolName,UnFoundFatal=UnFoundFatal)
165
Values => Var % Values
166
Perm => Var % Perm
167
168
PVar => VariableGet( Solver % Mesh % Variables, PSolName,UnFoundFatal=UnFoundFatal)
169
PValues => PVar % Values
170
PPerm => PVar % Perm
171
172
GradVar => VariableGet( Solver % Mesh % Variables, GradSolName,UnFoundFatal=UnFoundFatal)
173
GradValues => GradVar % Values
174
GradPerm => GradVar % Perm
175
176
x(1:NActiveNodes)=Values(Perm(ActiveNodes(1:NActiveNodes)))
177
g(1:NActiveNodes)=GradValues(GradPerm(ActiveNodes(1:NActiveNodes)))
178
xp(1:NActiveNodes)=PValues(PPerm(ActiveNodes(1:NActiveNodes)))
179
180
!!!!!! On calcul la dervivee totale à partir de la valeur du
181
!gradient
182
dJ=0._dp
183
Do i=1,NActiveNodes
184
dJ=dJ+xp(i)*g(i)
185
End do
186
deallocate(g)
187
188
IF (Parallel) THEN
189
CALL MPI_ALLREDUCE(dJ,dJ,1,&
190
MPI_DOUBLE_PRECISION,MPI_SUM,MPI_COMM_WORLD,ierr)
191
ENDIF
192
193
194
!!!!! On sauve la valeur de J0 pour le calcul diffrence fini.
195
J0=CostValues(1)
196
197
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
198
h=1.0_dp
199
Do i=1,NActiveNodes
200
Values(Perm(ActiveNodes(i)))=x(i)+h*xp(i)
201
End do
202
203
204
FirstVisit=.FALSE.
205
Return
206
End if
207
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
208
209
CostVar => VariableGet( Solver % Mesh % Variables, CostSolName,UnFoundFatal=UnFoundFatal)
210
CostValues => CostVar % Values
211
212
Var => VariableGet( Solver % Mesh % Variables, VarSolName,UnFoundFatal=UnFoundFatal)
213
Values => Var % Values
214
Perm => Var % Perm
215
216
217
J=CostValues(1)
218
219
dJd=(J-J0)/h
220
221
IF (Parallel) MyPe=ParEnv % MyPe
222
IF ((Parallel.AND.(MyPe.EQ.0)).OR.(.NOT.Parallel)) Then
223
open(io,file=trim(ResultFile),position='append')
224
write(io,'(4(e15.8,2x))') h,abs(dJ-dJd)/abs(dJ),dJ,dJd
225
close(io)
226
ENDIF
227
228
h=h/2.0_dp
229
Do i=1,NActiveNodes
230
Values(Perm(ActiveNodes(i)))=x(i)+h*xp(i)
231
End Do
232
233
Return
234
!------------------------------------------------------------------------------
235
END SUBROUTINE GradientValidation
236
!------------------------------------------------------------------------------
237
238
239
240