Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/Adjoint/Adjoint_CostContSolver.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:
30
! *
31
! *****************************************************************************
32
SUBROUTINE Adjoint_CostContSolver_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_CostContSolver_init0
52
!----------------------------------------------------------------------
53
! *****************************************************************************
54
SUBROUTINE Adjoint_CostContSolver( Model,Solver,dt,TransientSimulation )
55
!------------------------------------------------------------------------------
56
!Compute a Cost function as: Integral Node_Cost ds
57
!
58
! OUTPUT are : J and xb (sensitivity of J w.r.t. u)
59
60
! !! Be careful this solver will reset the cost and xb to 0;
61
! so it has to be used as the first cost solver in an inverse problem sequence
62
!
63
! see documentation under : elmerice/Solvers/Documentation/Adjoint_CostContSolver.md
64
!******************************************************************************
65
USE DefUtils
66
IMPLICIT NONE
67
!------------------------------------------------------------------------------
68
TYPE(Solver_t) :: Solver
69
TYPE(Model_t) :: Model
70
71
REAL(KIND=dp) :: dt
72
LOGICAL :: TransientSimulation
73
!
74
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName="Adjoint_CostContSolver"
75
CHARACTER(LEN=MAX_NAME_LEN), PARAMETER :: DefaultCostFile = 'CostOfT.dat'
76
CHARACTER(LEN=MAX_NAME_LEN),SAVE :: CostFile
77
CHARACTER(LEN=MAX_NAME_LEN),SAVE :: CostSolName
78
CHARACTER(LEN=MAX_NAME_LEN),SAVE :: VbName
79
CHARACTER(LEN=MAX_NAME_LEN) :: DerName
80
81
TYPE(Variable_t), POINTER :: TimeVar,CostVar
82
TYPE(Variable_t), POINTER :: VbSol
83
REAL(KIND=dp), POINTER :: Vb(:)
84
INTEGER, POINTER :: VbPerm(:)
85
INTEGER,SAVE :: VDOFs
86
87
TYPE(ValueList_t), POINTER :: SolverParams,BodyForce
88
89
TYPE(Element_t),POINTER :: Element
90
TYPE(Nodes_t),SAVE :: ElementNodes
91
TYPE(GaussIntegrationPoints_t) :: IntegStuff
92
INTEGER, POINTER :: NodeIndexes(:)
93
REAL(KIND=dp),ALLOCATABLE,SAVE :: Basis(:),dBasisdx(:,:)
94
REAL(KIND=dp) :: u,v,w,SqrtElementMetric,x,s
95
INTEGER :: n
96
97
LOGICAL,SAVE :: Firsttime=.TRUE.
98
LOGICAL,SAVE :: Parallel
99
LOGICAL :: BoundarySolver
100
101
LOGICAL :: Found,stat
102
integer :: i,j,k,t
103
INTEGER :: ierr
104
real(kind=dp) :: Cost,Cost_S
105
real(kind=dp) :: Area,Area_S
106
real(kind=dp) :: coeff
107
108
REAL(KIND=dp),ALLOCATABLE,SAVE :: NodeCost(:)
109
REAL(KIND=dp),ALLOCATABLE,SAVE :: NodeCostb(:),NodeCost_der(:,:)
110
111
INTEGER, SAVE :: DIM
112
113
CHARACTER*10 :: date,temps
114
115
116
SolverParams => GetSolverParams()
117
118
If (Firsttime) then
119
N = model % MaxElementNodes
120
allocate(ElementNodes % x(N), ElementNodes % y(N), ElementNodes % z(N))
121
allocate(Basis(N),dBasisdx(N,3))
122
123
!!!!!!! Check for parallel run
124
!Parallel = .FALSE.
125
!IF ( ASSOCIATED( Solver % Matrix % ParMatrix ) ) THEN
126
! IF ( Solver % Matrix % ParMatrix % ParEnv % PEs > 1 ) THEN
127
! Parallel = .TRUE.
128
! END IF
129
!END IF
130
Parallel = ParEnv % PEs > 1
131
132
IF(ASSOCIATED(Solver % ActiveElements)) THEN
133
!! check if we are on a boundary or in the bulk
134
BoundarySolver = ( Solver % ActiveElements(1) > Model % Mesh % NumberOfBulkElements )
135
ELSE
136
BoundarySolver = .TRUE. ! must be true for other parts if no elements present
137
! if not boundarysolver would have active elements
138
END IF
139
140
IF (BoundarySolver) THEN
141
DIM = CoordinateSystemDimension() - 1
142
ELSE
143
DIM = CoordinateSystemDimension()
144
ENDIF
145
146
!!!!!!!!!!! get Solver Variables
147
CostFile = ListGetString(Solver % Values,'Cost Filename',Found )
148
IF (.NOT. Found) CostFile = DefaultCostFile
149
CALL DATE_AND_TIME(date,temps)
150
If (Parallel) then
151
if (ParEnv % MyPe.EQ.0) then
152
OPEN (12, FILE=CostFile)
153
write(12,1000) date(5:6),date(7:8),date(1:4),temps(1:2),temps(3:4),temps(5:6)
154
write(12,'(A)') '#, 1.0'
155
write(12,'(A)') '# iter, J0, sqrt(2J0/Area)'
156
CLOSE(12)
157
End if
158
Else
159
OPEN (12, FILE=CostFile)
160
write(12,1000) date(5:6),date(7:8),date(1:4),temps(1:2),temps(3:4),temps(5:6)
161
write(12,'(A)') '#, 1.0'
162
write(12,'(A)') '# iter, J0, sqrt(2J0/Area)'
163
CLOSE(12)
164
End if
165
166
CostSolName = GetString( SolverParams,'Cost Variable Name', Found)
167
IF(.NOT.Found) THEN
168
CALL WARN(SolverName,'Keyword >Cost Variable Name< not found in section >Solver<')
169
CALL WARN(SolverName,'Taking default value >CostValue<')
170
WRITE(CostSolName,'(A)') 'CostValue'
171
END IF
172
173
VbName = ListGetString(SolverParams,'Sensitivity Variable Name', UnFoundFatal=.TRUE.)
174
VbSol => VariableGet( Solver % Mesh % Variables,TRIM(VbName), UnFoundFatal=.TRUE. )
175
VDOFs = VbSol % DOFs
176
allocate(NodeCost(N),NodeCostb(N),NodeCost_der(VDOFs,N))
177
178
!!! End of First visit
179
Firsttime=.false.
180
Endif
181
182
VbSol => VariableGet( Solver % Mesh % Variables,TRIM(VbName), UnFoundFatal=.TRUE. )
183
Vb => VbSol % Values
184
VbPerm => VbSol % Perm
185
Vb=0.0_dp
186
187
Cost=0._dp
188
Area=0._dp
189
190
DO t=1,Solver % NumberOfActiveElements
191
Element => GetActiveElement(t)
192
IF (CheckPassiveElement(Element)) CYCLE
193
n = GetElementNOFNodes()
194
195
NodeIndexes => Element % NodeIndexes
196
197
! set coords of highest occurring dimension to zero (to get correct path element)
198
!-------------------------------------------------------------------------------
199
ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)
200
IF (DIM == 1) THEN !1D
201
ElementNodes % y(1:n) = 0.0_dp
202
ElementNodes % z(1:n) = 0.0_dp
203
ELSE IF (DIM == 2) THEN !2D
204
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
205
ElementNodes % z(1:n) = 0.0_dp
206
ELSE IF (DIM == 3) THEN
207
ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)
208
ElementNodes % z(1:n) = Solver % Mesh % Nodes % z(NodeIndexes)
209
END IF
210
211
BodyForce => GetBodyForce(Element)
212
213
NodeCost=0.0_dp
214
NodeCost(1:n) = ListGetReal( BodyForce, 'Adjoint Cost', n, NodeIndexes, UnFoundFatal=.TRUE.)
215
NodeCost_der=0.0_dp
216
217
IF (VDOFs.EQ.1) THEN
218
DerName='Adjoint Cost der'
219
IF(.NOT. ListCheckPresent( BodyForce,TRIM(DerName))) &
220
DerName='Adjoint Cost der ' // I2S(1)
221
NodeCost_der(1,1:n)=ListGetReal( BodyForce,DerName, n, NodeIndexes, UnFoundFatal=.TRUE.)
222
ELSE
223
DO k=1,VDOFs
224
DerName=ComponentName("Adjoint Cost der",k)
225
NodeCost_der(k,1:n)=ListGetReal( BodyForce,TRIM(DerName), n, NodeIndexes, Found)
226
IF (.NOT.Found) NodeCost_der(k,1:n)=0._dp
227
END DO
228
END IF
229
230
!------------------------------------------------------------------------------
231
! Numerical integration
232
!------------------------------------------------------------------------------
233
IntegStuff = GaussPoints( Element )
234
235
NodeCostb=0.0_dp
236
237
DO i=1,IntegStuff % n
238
U = IntegStuff % u(i)
239
V = IntegStuff % v(i)
240
W = IntegStuff % w(i)
241
!------------------------------------------------------------------------------
242
! Basis function values & derivatives at the integration point
243
!------------------------------------------------------------------------------
244
stat = ElementInfo( Element,ElementNodes,U,V,W,SqrtElementMetric, &
245
Basis,dBasisdx )
246
247
x = SUM( ElementNodes % x(1:n) * Basis(1:n) )
248
s = 1.0d0
249
250
IF ( CurrentCoordinateSystem() /= Cartesian ) THEN
251
s = 2.0d0 * PI * x
252
END IF
253
s = s * SqrtElementMetric * IntegStuff % s(i)
254
255
coeff = SUM(NodeCost(1:n) * Basis(1:n))
256
Cost=Cost+coeff*s
257
Area=Area+s
258
259
NodeCostb(1:n)=NodeCostb(1:n) + s*Basis(1:n)
260
261
End do
262
263
Do j=1,n
264
Do i=1,VDOFs
265
k=(VbPerm(NodeIndexes(j))-1)*VDOFs+i
266
Vb(k)=Vb(k)+NodeCostb(j)*NodeCost_der(i,j)
267
End Do
268
End Do
269
End do
270
271
TimeVar => VariableGet( Solver % Mesh % Variables, 'Time' )
272
273
IF (Parallel) THEN
274
CALL MPI_ALLREDUCE(Cost,Cost_S,1,&
275
MPI_DOUBLE_PRECISION,MPI_SUM,ELMER_COMM_WORLD,ierr)
276
277
CALL MPI_ALLREDUCE(Area,Area_S,1,&
278
MPI_DOUBLE_PRECISION,MPI_SUM,ELMER_COMM_WORLD,ierr)
279
280
CostVar => VariableGet( Solver % Mesh % Variables, CostSolName )
281
IF (ASSOCIATED(CostVar)) THEN
282
CostVar % Values(1)=Cost_S
283
END IF
284
IF (ParEnv % MyPE == 0) then
285
OPEN (12, FILE=CostFile,POSITION='APPEND')
286
write(12,'(3(ES20.11E3))') TimeVar % Values(1),Cost_S,sqrt(2*Cost_S/Area_S)
287
CLOSE(12)
288
End if
289
ELSE
290
CostVar => VariableGet( Solver % Mesh % Variables, CostSolName )
291
IF (ASSOCIATED(CostVar)) THEN
292
CostVar % Values(1)=Cost
293
END IF
294
OPEN (12, FILE=CostFile,POSITION='APPEND')
295
write(12,'(3(ES20.11E3))') TimeVar % Values(1),Cost,sqrt(2*Cost/Area)
296
close(12)
297
Cost_S=Cost
298
END IF
299
300
Solver % Variable % Values(1)=Cost_S
301
302
Return
303
304
1000 format('#date,time,',a2,'/',a2,'/',a4,',',a2,':',a2,':',a2)
305
!------------------------------------------------------------------------------
306
END SUBROUTINE Adjoint_CostContSolver
307
!------------------------------------------------------------------------------
308
! *****************************************************************************
309
310