Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/AdjointSSA/AdjointSSA_AdjointSolver.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:
26
! * Email:
27
! * Web: http://elmerice.elmerfem.org
28
! *
29
! * Original Date:
30
! *
31
! *****************************************************************************
32
!------------------------------------------------------------------------------
33
SUBROUTINE AdjointSSA_AdjointSolver( Model,Solver,dt,TransientSimulation )
34
!------------------------------------------------------------------------------
35
!> Compute the adjoint state of the SSA equations.
36
!
37
! OUTPUT is : Solver % Variable the adjoint state of the SSA problem
38
!
39
! INPUT PARAMETERS are:
40
!
41
! In solver section:
42
! Flow Solution Equation Name = String (default 'SSA')
43
!
44
! Variables
45
! Velocityb (forcing for the adjoint pb)
46
!
47
!******************************************************************************
48
! ARGUMENTS:
49
!
50
! TYPE(Model_t) :: Model,
51
! INPUT: All model information (mesh, materials, BCs, etc...)
52
!
53
! TYPE(Solver_t) :: Solver
54
! INPUT: Linear & nonlinear equation solver options
55
!
56
! REAL(KIND=dp) :: dt,
57
! INPUT: Timestep size for time dependent simulations
58
!
59
! LOGICAL :: TransientSimulation
60
! INPUT: Steady state or transient simulation
61
!
62
!******************************************************************************
63
USE DefUtils
64
IMPLICIT NONE
65
!------------------------------------------------------------------------------
66
TYPE(Solver_t) :: Solver
67
TYPE(Model_t) :: Model
68
REAL(KIND=dp) :: dt
69
LOGICAL :: TransientSimulation
70
!------------------------------------------------------------------------------
71
! Local variables
72
!------------------------------------------------------------------------------
73
TYPE(Solver_t),Pointer :: NSSolver
74
TYPE(Matrix_t),POINTER :: InitMat,TransMat,StiffMatrix
75
TYPE(ValueList_t),POINTER :: BC,BF,SolverParams
76
TYPE(ValueListEntry_t),POINTER :: NormalTangential,NormalTangentialC
77
character(LEN=MAX_NAME_LEN),SAVE :: NormalTangentialName,NormalTangentialNameb
78
LOGICAL :: AnyNT
79
TYPE(Element_t),POINTER :: Element
80
TYPE(Variable_t), POINTER :: Sol
81
TYPE(Variable_t), POINTER :: VelocitybSol
82
REAL(KIND=dp), POINTER :: Vb(:)
83
INTEGER, POINTER :: VbPerm(:)
84
REAL(KIND=dp),POINTER :: ForceVector(:)
85
integer :: i,j,k,t,n,NSDOFs
86
INTEGER :: kmax
87
Logical :: Gotit
88
INTEGER, POINTER :: NodeIndexes(:),Perm(:)
89
integer :: p,q,dim,c,m
90
Real(KIND=dp) :: Unorm
91
Real(KIND=dp) :: RotVec(3)
92
character(LEN=MAX_NAME_LEN) :: SolName,NSVarName
93
LOGICAL :: Conditional,CheckNT
94
REAL(KIND=dp),ALLOCATABLE,SAVE :: Condition(:)
95
96
INTEGER, POINTER,SAVE :: BoundaryReorder(:)=> NULL()
97
INTEGER,SAVE :: NormalTangentialNOFNodes
98
REAL(KIND=dp), POINTER :: BoundaryNormals(:,:)=> NULL(), &
99
BoundaryTangent1(:,:)=> NULL(), &
100
BoundaryTangent2(:,:)=> NULL()
101
102
CHARACTER(LEN=MAX_NAME_LEN),SAVE :: SolverName="Adjoint Solver"
103
INTEGER, SAVE :: SolverInd
104
LOGICAL, SAVE :: Firsttime=.TRUE.
105
106
107
CALL Info(SolverName,'***********************',level=0)
108
CALL Info(SolverName,' This solver has been replaced by:',level=0)
109
CALL Info(SolverName,' Adjoint_LinearSolver ',level=0)
110
CALL Info(SolverName,' See documentation under: ',level=0)
111
CALL Info(SolverName,' elmerice/Solvers/Documentation ',level=0)
112
CALL Info(SolverName,'***********************',level=0)
113
CALL FATAL(SolverName,' Use new solver !!')
114
115
116
DIM = CoordinateSystemDimension()
117
118
StiffMatrix => Solver % Matrix
119
ForceVector => StiffMatrix % RHS
120
121
Sol => Solver % Variable
122
NSDOFs = Sol % DOFs
123
Perm => Sol % Perm
124
125
! IF DIM = 3 and NSDOFs=2; Normal-Tangential can not be used => trick temporary set
126
! Model Dimension to 2
127
IF (DIM.eq.(NSDOFs+1)) CurrentModel % Dimension = NSDOFs
128
129
130
IF (Firsttime) then
131
Firsttime=.False.
132
133
N = Model % MaxElementNodes
134
ALLOCATE(Condition(N))
135
136
SolverParams => GetSolverParams(Solver)
137
SolName = ListGetString( SolverParams,'Flow Solution Equation Name',GotIt)
138
IF (.NOT.Gotit) Then
139
CALL WARN(SolverName,'Keyword >Flow Solution Equation Name< not found in SolverParams')
140
CALL WARN(SolverName,'Taking default value >SSA<')
141
WRITE(SolName,'(A)') 'SSA'
142
Endif
143
DO i=1,Model % NumberOfSolvers
144
if (TRIM(SolName) == ListGetString(Model % Solvers(i) % Values, 'Equation')) exit
145
End do
146
if (i.eq.(Model % NumberOfSolvers+1)) &
147
CALL FATAL(SolverName,'Could not find Equation Name ' // TRIM(SolName))
148
149
SolverInd=i
150
NSSolver => Model % Solvers(SolverInd)
151
152
!# Check For NT boundaries
153
NormalTangentialName = 'normal-tangential'
154
IF ( SEQL(NSSolver % Variable % Name, 'flow solution') ) THEN
155
NormalTangentialName = TRIM(NormalTangentialName) // ' velocity'
156
ELSE
157
NormalTangentialName = TRIM(NormalTangentialName) // ' ' // &
158
GetVarName(NSSolver % Variable)
159
END IF
160
161
AnyNT = ListGetLogicalAnyBC( Model, TRIM(NormalTangentialName) )
162
IF (AnyNT) THEN
163
164
!# We will stay in NT to impose dirichlet conditions
165
CALL ListAddLogical(SolverParams,'Back Rotate N-T Solution',.FALSE.)
166
167
!# !!! Has to be in lower case to copy item
168
NormalTangentialNameb='normal-tangential' // ' ' // GetVarName(Solver % Variable)
169
170
DO i=1,Model % NumberOfBCs
171
BC => Model % BCs(i) % Values
172
NormalTangential => ListFind( BC , NormalTangentialName , GotIt )
173
IF (.NOT.Gotit) CYCLE
174
175
WRITE(Message,'(A,I0)') 'Copy Normal-Tangential keyword in BC ',i
176
CALL Info(SolverName,Message,level=4)
177
CALL ListCopyItem( NormalTangential, BC, NormalTangentialNameb)
178
179
NormalTangentialC => ListFind( BC , TRIM(NormalTangentialName) // ' condition' , GotIt )
180
IF (.NOT.Gotit) CYCLE
181
182
WRITE(Message,'(A,I0)') 'Copy Normal-Tangential Condition keyword in BC ',i
183
CALL Info(SolverName,Message,level=4)
184
CALL ListCopyItem( NormalTangentialC, BC, TRIM(NormalTangentialNameb) // ' condition' )
185
END DO
186
187
CALL CheckNormalTangentialBoundary( Model, TRIM(NormalTangentialNameb), &
188
NormalTangentialNOFNodes, BoundaryReorder, &
189
BoundaryNormals, BoundaryTangent1, BoundaryTangent2, dim )
190
191
END IF
192
END IF
193
194
195
NSSolver => Model % Solvers(SolverInd)
196
197
IF ( SEQL(NSSolver % Variable % Name, 'flow solution') ) THEN
198
NSVarName = 'Velocity'
199
ELSE
200
NSVarName = GetVarName(NSSolver % Variable)
201
END IF
202
203
CALL DefaultInitialize()
204
205
InitMat => AllocateMatrix()
206
InitMat % NumberOfRows = NSSolver % Matrix % NumberOfRows
207
InitMat % Values => NSSolver % Matrix % Values
208
InitMat % Rows => NSSolver % Matrix % Rows
209
InitMat % Cols => NSSolver % Matrix % Cols
210
InitMat % Diag => NSSolver % Matrix % Diag
211
212
213
VelocitybSol => VariableGet( Solver % Mesh % Variables, 'Velocityb' )
214
IF ( ASSOCIATED( VelocitybSol ) ) THEN
215
Vb => VelocitybSol % Values
216
VbPerm => VelocitybSol % Perm
217
ELSE
218
WRITE(Message,'(A)') 'No variable > Velocityb < found'
219
CALL FATAL(SolverName,Message)
220
END IF
221
IF (VelocitybSol % DOFs.NE.NSDOFs) then
222
WRITE(Message,'(A,I1,A,I1)') &
223
'Variable Velocityb has ',VelocitybSol % DOFs,' DOFs, should be',NSDOFs
224
CALL FATAL(SolverName,Message)
225
END IF
226
227
TransMat => NULL()
228
TransMat => CRS_Transpose(InitMat)
229
230
NULLIFY( InitMat % Rows, InitMat % Cols, InitMat % Diag, InitMat % Values )
231
CALL FreeMatrix( InitMat )
232
233
CALL CRS_SortMatrix( TransMat , .true. )
234
235
StiffMatrix % Values = TransMat % Values
236
StiffMatrix % Rows = TransMat % Rows
237
StiffMatrix % Cols = TransMat % Cols
238
IF(ASSOCIATED(TransMat % Diag)) StiffMatrix % Diag = TransMat % Diag
239
ForceVector = 0.0
240
Perm = NSSolver % Variable % Perm
241
242
deallocate( TransMat % Rows, TransMat % Cols , TransMat % Values)
243
IF(ASSOCIATED(TransMat % Diag)) DEALLOCATE(TransMat % Diag)
244
nullify(TransMat)
245
246
!forcing of the adjoint system comes from the Velocityb variable computed
247
!with the cost function
248
249
!! Vb is expressed in the model coordinate system => Rotate to NT
250
CALL RotateNTSystemAll( Vb, VbPerm, NSDOFs )
251
252
c = NSDOFs
253
Do t=1,Solver%Mesh%NumberOfNodes
254
Do i=1,c
255
p=(Perm(t)-1)*c+i
256
q=(VbPerm(t)-1)*c+i
257
ForceVector(p)=Vb(q)
258
End Do
259
EndDo
260
261
CALL FinishAssembly( Solver, ForceVector )
262
263
Unorm = DefaultSolve()
264
265
! Go through BC to check if dirichlet was applied to direct solver
266
! Go to the boundary elements
267
Do t=1,GetNOFBoundaryElements()
268
Element => GetBoundaryElement(t)
269
BC => GetBC(Element)
270
IF (.NOT.ASSOCIATED( BC ) ) CYCLE
271
272
NodeIndexes => Element % NodeIndexes
273
n = Element % TYPE % NumberOfNodes
274
275
! Cf correspond lines in SolverUtils
276
! Check for nodes belonging to n-t boundary getting set by other bcs.
277
! -------------------------------------------------------------------
278
CheckNT = .FALSE.
279
IF ( NormalTangentialNOFNodes>0 .AND. NSDOFs>0 ) THEN
280
CheckNT = .TRUE.
281
IF ( ALL(BoundaryReorder(NodeIndexes(1:n))<1) ) CheckNT = .FALSE.
282
IF ( ListGetLogical(BC,'normal-tangential' // ' ' // NSVarName,Gotit)) CheckNT=.FALSE.
283
END IF
284
285
! set BC for NSDOFs=1 or applied to the whole vector
286
IF( ListCheckPresent( BC, NSVarName ) ) THEN
287
Condition(1:n) = ListGetReal( BC, &
288
TRIM(NSVarName) // ' Condition', n, NodeIndexes, Conditional )
289
DO j=1,n
290
IF ( Conditional .AND. Condition(j)<0._dp ) CYCLE
291
DO i=1,NSDOFS
292
Sol%Values(NSDOFs*(Perm(NodeIndexes(j))-1)+i)=0._dp
293
END DO
294
END DO
295
ENDIF
296
297
! Do the same for each component
298
IF (NSDOFs>1) THEN
299
DO i=1,NSDOFS
300
IF( ListCheckPresent( BC, ComponentName(NSVarName,i)) ) THEN
301
Condition(1:n) = ListGetReal( BC, &
302
TRIM(ComponentName(NSVarName,i)) // ' Condition', n, NodeIndexes, Conditional )
303
304
DO j=1,n
305
IF ( Conditional .AND. Condition(j)<0._dp ) CYCLE
306
307
k = Perm(NodeIndexes(j))
308
IF ( k > 0 ) THEN
309
310
m = 0
311
IF ( NormalTangentialNOFNodes>0 ) m=BoundaryReorder(NodeIndexes(j))
312
!! set in the NT system
313
IF ( m>0 .AND. CheckNT ) THEN
314
RotVec = 0._dp
315
RotVec(i) = 1._dp
316
CALL RotateNTSystem( RotVec, NodeIndexes(j) )
317
318
! When cartesian component "DOF" is defined set the N-T component
319
! closest to its direction.
320
kmax = 1
321
DO k=2,dim
322
IF ( ABS(RotVec(k)) > ABS(RotVec(kmax)) ) THEN
323
kmax = k
324
END IF
325
END DO
326
Sol%Values(NSDOFs*(Perm(NodeIndexes(j))-1) + kmax)=0._dp
327
!else set the given DOF
328
ELSE
329
Sol%Values(NSDOFs*(Perm(NodeIndexes(j))-1)+i)=0._dp
330
END IF
331
332
ENDIF
333
END DO
334
335
ENDIF
336
337
END DO
338
ENDIF
339
END DO
340
341
! Go through the Body forces
342
Do t=1,Solver % NumberOfActiveElements
343
Element => GetActiveElement(t)
344
345
BF => GetBodyForce(Element)
346
IF (.NOT.ASSOCIATED( BF ) ) CYCLE
347
348
NodeIndexes => Element % NodeIndexes
349
n = Element % TYPE % NumberOfNodes
350
351
! set BC for NSDOFs=1 or applied to the whole vector
352
IF( ListCheckPresent( BF, NSVarName ) ) THEN
353
Condition(1:n) = ListGetReal( BF, &
354
TRIM(NSVarName) // ' Condition', n, NodeIndexes, Conditional )
355
DO j=1,n
356
IF ( Conditional .AND. Condition(j)<0._dp ) CYCLE
357
DO i=1,NSDOFS
358
Sol%Values(NSDOFs*(Perm(NodeIndexes(j))-1)+i)=0._dp
359
END DO
360
END DO
361
ENDIF
362
363
! Do the same for each component
364
IF (NSDOFs>1) THEN
365
DO i=1,NSDOFS
366
IF( ListCheckPresent( BF, ComponentName(NSVarName,i)) ) THEN
367
Condition(1:n) = ListGetReal( BF, &
368
TRIM(ComponentName(NSVarName,i)) // ' Condition', n, NodeIndexes, Conditional )
369
370
DO j=1,n
371
IF ( Conditional .AND. Condition(j)<0._dp ) CYCLE
372
Sol%Values(NSDOFs*(Perm(NodeIndexes(j))-1)+i)=0._dp
373
END DO
374
END IF
375
END DO
376
END IF
377
378
END DO
379
380
! Back Rotate to model coordinate system
381
CALL BackRotateNTSystem(Sol%Values,Perm,NSDOFs)
382
383
! reset Dimension to DIM
384
IF (DIM.eq.(NSDOFs+1)) CurrentModel % Dimension = DIM
385
386
RETURN
387
!------------------------------------------------------------------------------
388
END SUBROUTINE AdjointSSA_AdjointSolver
389
!------------------------------------------------------------------------------
390
391
392