Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/AdjointStokes/AdjointStokes_GradientBetaSolver.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
! Adjoint of the Stokes problem for the slip coefficient
33
! Provide the derivative with respect to the slip coef.
34
!
35
! Serial/Parallel(not halo?) and 2D/3D
36
!
37
! Need:
38
! - Navier-stokes and Adjoint Problems Solutions
39
! - Grad Variable
40
!
41
! *****************************************************************************
42
SUBROUTINE AdjointStokes_GradientBetaSolver_init0(Model,Solver,dt,TransientSimulation )
43
!------------------------------------------------------------------------------
44
USE DefUtils
45
IMPLICIT NONE
46
!------------------------------------------------------------------------------
47
TYPE(Solver_t), TARGET :: Solver
48
TYPE(Model_t) :: Model
49
REAL(KIND=dp) :: dt
50
LOGICAL :: TransientSimulation
51
!------------------------------------------------------------------------------
52
! Local variables
53
!------------------------------------------------------------------------------
54
CHARACTER(LEN=MAX_NAME_LEN) :: Name
55
56
Name = ListGetString( Solver % Values, 'Equation',UnFoundFatal=.TRUE.)
57
CALL ListAddNewString( Solver % Values,'Variable',&
58
'-nooutput '//TRIM(Name)//'_var')
59
CALL ListAddLogical(Solver % Values, 'Optimize Bandwidth',.FALSE.)
60
61
END SUBROUTINE AdjointStokes_GradientBetaSolver_init0
62
! *****************************************************************************
63
SUBROUTINE AdjointStokes_GradientBetaSolver( Model,Solver,dt,TransientSimulation )
64
!------------------------------------------------------------------------------
65
!******************************************************************************
66
USE DefUtils
67
IMPLICIT NONE
68
!------------------------------------------------------------------------------
69
TYPE(Solver_t) :: Solver
70
TYPE(Model_t) :: Model
71
72
REAL(KIND=dp) :: dt
73
LOGICAL :: TransientSimulation
74
!
75
TYPE(ValueList_t), POINTER :: SolverParams
76
TYPE(ValueList_t), POINTER :: BC
77
78
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName="AdjointStokes_GradientBeta"
79
80
INTEGER,SAVE :: DIM
81
82
CHARACTER(LEN=MAX_NAME_LEN),SAVE :: NeumannSolName,AdjointSolName
83
TYPE(Variable_t), POINTER :: VeloSolN,VeloSolD
84
REAL(KIND=dp), POINTER :: VelocityN(:),VelocityD(:)
85
INTEGER, POINTER :: VeloNPerm(:),VeloDPerm(:)
86
87
CHARACTER(LEN=MAX_NAME_LEN),SAVE :: GradSolName
88
TYPE(Variable_t), POINTER :: PointerToVariable
89
REAL(KIND=dp), POINTER :: VariableValues(:)
90
INTEGER, POINTER :: Permutation(:)
91
92
TYPE(Element_t),POINTER :: Element
93
TYPE(Nodes_t),SAVE :: ElementNodes
94
INTEGER, POINTER :: NodeIndexes(:)
95
TYPE(GaussIntegrationPoints_t) :: IntegStuff
96
REAL(kind=dp) :: u,v,w,SqrtElementMetric,s
97
REAL(kind=dp),allocatable,SAVE :: Basis(:),dBasisdx(:,:)
98
INTEGER :: n
99
100
LOGICAL :: NormalTangential1,NormalTangential2
101
REAL(KIND=dp) :: Normal(3),Tangent(3),Tangent2(3),Vect(3)
102
REAL(kind=dp) :: betab
103
REAL(kind=dp),allocatable,SAVE :: NodalDer(:),NodalGrad(:)
104
LOGICAL :: HaveDer
105
106
INTEGER :: NMAX
107
108
integer :: i,j,k,p,q,e,t
109
110
LOGICAL :: Found,stat
111
LOGICAL :: Reset
112
LOGICAL, SAVE :: Firsttime=.true.
113
LOGICAL,PARAMETER :: UnFoundFatal=.TRUE.
114
115
TYPE(ValueHandle_t), SAVE :: WeertmanCoeff_h,WeertmanExp_h,FrictionUt0_h,FrictionNormal_h
116
TYPE(VariableHandle_t), SAVE :: Velo_v
117
LOGICAL :: HaveFrictionW
118
REAL(KIND=dp) :: wut0
119
LOGICAL :: FrictionNormal
120
REAL(KIND=dp) :: Velo(3),un,ut,TanFrictionCoeff,wexp, wcoeff
121
122
123
SolverParams => GetSolverParams()
124
125
If (Firsttime) then
126
127
DIM = CoordinateSystemDimension()
128
129
NMAX=Model % MaxElementNodes
130
allocate(Basis(NMAX),dBasisdx(NMAX,3))
131
allocate(NodalDer(NMAX),NodalGrad(NMAX))
132
!!!!!!!!!!! get Solver Variables
133
134
NeumannSolName = GetString( SolverParams,'Flow Solution Name', Found)
135
IF(.NOT.Found) THEN
136
CALL WARN(SolverName,'Keyword >Neumann Solution Name< not found in section >Solver<')
137
CALL WARN(SolverName,'Taking default value >Flow Solution<')
138
WRITE(NeumannSolName,'(A)') 'Flow Solution'
139
END IF
140
AdjointSolName = GetString( SolverParams,'Adjoint Solution Name', Found)
141
IF(.NOT.Found) THEN
142
CALL WARN(SolverName,'Keyword >Adjoint Solution Name< not found in section >Solver<')
143
CALL WARN(SolverName,'Taking default value >Adjoint<')
144
WRITE(AdjointSolName,'(A)') 'Adjoint'
145
END IF
146
147
GradSolName = GetString( SolverParams,'Gradient Variable Name', Found)
148
IF(.NOT.Found) THEN
149
CALL WARN(SolverName,'Keyword >Gradient Variable Name< not found in section >Solver<')
150
CALL WARN(SolverName,'Taking default value >DJDB<')
151
WRITE(GradSolName,'(A)') 'DJDB'
152
END IF
153
154
!!!! Handles initialisation
155
CALL ListInitElementKeyword( WeertmanCoeff_h,'Boundary Condition','Weertman Friction Coefficient')
156
CALL ListInitElementKeyword( WeertmanExp_h,'Boundary Condition','Weertman Exponent')
157
CALL ListInitElementKeyword( FrictionUt0_h,'Boundary Condition','Friction Linear Velocity')
158
CALL ListInitElementKeyword( FrictionNormal_h,'Boundary Condition','Friction Normal Velocity Zero')
159
CALL ListInitElementVariable( Velo_v , NeumannSolName , Found=Found)
160
IF (.NOT.Found) &
161
CALL FATAL(SolverName,TRIM(NeumannSolName)//' Variable not found')
162
163
!!! End of First visit
164
Firsttime=.false.
165
Endif
166
167
PointerToVariable => VariableGet( Model % Mesh % Variables, GradSolName,UnFoundFatal=UnFoundFatal)
168
VariableValues => PointerToVariable % Values
169
Permutation => PointerToVariable % Perm
170
Reset = ListGetLogical( SolverParams,'Reset Gradient Variable', Found)
171
if (Reset.OR.(.NOT.Found)) VariableValues=0._dp
172
173
VeloSolN => VariableGet( Model % Mesh % Variables, NeumannSolName,UnFoundFatal=UnFoundFatal)
174
VelocityN => VeloSolN % Values
175
VeloNPerm => VeloSolN % Perm
176
177
VeloSolD => VariableGet( Model % Mesh % Variables, AdjointSolName,UnFoundFatal=UnFoundFatal)
178
VelocityD => VeloSolD % Values
179
VeloDPerm => VeloSolD % Perm
180
181
182
183
DO e=1,Solver % NumberOfActiveElements
184
Element => GetActiveElement(e)
185
CALL GetElementNodes( ElementNodes )
186
n = GetElementNOFNodes(Element)
187
NodeIndexes => Element % NodeIndexes
188
189
! Compute Nodal Value of DJDBeta
190
BC => GetBC(Element)
191
if (.NOT.ASSOCIATED(BC)) &
192
CALL FATAL(SolverName,'This solver is intended to be executed on a BC')
193
194
NormalTangential1 = GetLogical( BC, &
195
'Normal-Tangential Velocity', Found )
196
IF (.NOT.Found) then
197
NormalTangential1 = GetLogical( BC, &
198
'Normal-Tangential '//trim(NeumannSolName), Found)
199
END IF
200
NormalTangential2 = GetLogical( BC, &
201
'Normal-Tangential '//trim(AdjointSolName), Found)
202
IF (NormalTangential1.NEQV.NormalTangential2) then
203
WRITE(Message,'(A,I1,A,I1)') &
204
'NormalTangential Velocity is : ',NormalTangential1, &
205
'But NormalTangential Adjoint is : ',NormalTangential2
206
CALL FATAL(SolverName,Message)
207
ENDIF
208
IF (.NOT.NormalTangential1) then
209
WRITE(Message,'(A)') &
210
'ALWAYS USE Normal-Tangential COORDINATES with SlipCoef 2=SlipCoef 3'
211
CALL FATAL(SolverName,Message)
212
ENDIF
213
214
HaveFrictionW = ListCheckPresent( BC,'Weertman Friction Coefficient')
215
IF (HaveFrictionW) THEN
216
wut0 = ListGetElementReal( FrictionUt0_h, Element = Element )
217
FrictionNormal = ListGetElementLogical( FrictionNormal_h, Element )
218
END IF
219
220
NodalDer(1:n) = ListGetReal(BC,'Slip Coefficient derivative',n,NodeIndexes,Found=HaveDer)
221
222
223
! Compute Integrated Nodal Value of DJDBeta
224
IntegStuff = GaussPoints( Element )
225
DO t=1,IntegStuff % n
226
U = IntegStuff % u(t)
227
V = IntegStuff % v(t)
228
W = IntegStuff % w(t)
229
stat = ElementInfo(Element,ElementNodes,U,V,W,SqrtElementMetric, &
230
Basis,dBasisdx )
231
232
s = SqrtElementMetric * IntegStuff % s(t)
233
234
! compute gradient from Stokes and adjoint computation
235
! follow the computation of the stiffMatrix as done in the NS solver
236
Normal = NormalVector( Element, ElementNodes, u,v,.TRUE. )
237
SELECT CASE( Element % TYPE % DIMENSION )
238
CASE(1)
239
Tangent(1) = Normal(2)
240
Tangent(2) = -Normal(1)
241
Tangent(3) = 0.0_dp
242
Tangent2 = 0.0_dp
243
CASE(2)
244
CALL TangentDirections( Normal, Tangent, Tangent2 )
245
END SELECT
246
247
248
betab=0.0_dp
249
Do p=1,n
250
Do q=1,n
251
252
Do i=2,dim
253
SELECT CASE(i)
254
CASE(2)
255
Vect = Tangent
256
CASE(3)
257
Vect = Tangent2
258
END SELECT
259
260
Do j=1,DIM
261
Do k=1,DIM
262
betab = betab + s * Basis(q) * Basis(p) * Vect(j) * Vect(k) * &
263
(- VelocityN((DIM+1)*(VeloNPerm(NodeIndexes(q))-1)+k) * &
264
VelocityD((DIM+1)*(VeloDPerm(NodeIndexes(p))-1)+j))
265
End Do !on k
266
End Do !on j
267
End Do !on i
268
End Do !on q
269
End Do !on p
270
271
IF (HaveDer) THEN
272
NodalGrad(1:n)=Basis(1:n)*NodalDer(1:n)
273
ELSE
274
NodalGrad(1:n)=Basis(1:n)
275
ENDIF
276
277
IF( HaveFrictionW) THEN
278
! Velocity at integration point for nonlinear friction laws
279
Velo = ListGetElementVectorSolution( Velo_v, Basis, Element, dofs = dim )
280
IF(.NOT. FrictionNormal ) THEN
281
un = SUM( Normal(1:dim) * Velo(1:dim) )
282
velo(1:dim) = velo(1:dim)-un*normal(1:dim)
283
END IF
284
ut = MAX(wut0, SQRT(SUM(Velo(1:dim)**2)))
285
286
!TanFrictionCoeff = MIN(wcoeff * ut**(wexp-1.0_dp),1.0e20)
287
wcoeff = ListGetElementReal( WeertmanCoeff_h, Basis, Element, GaussPoint = t )
288
wexp = ListGetElementReal( WeertmanExp_h, Basis, Element, GaussPoint = t )
289
TanFrictionCoeff=wcoeff * ut**(wexp-1.0_dp)
290
IF (TanFrictionCoeff.GE.1.0e20) THEN
291
betab=0._dp
292
ELSE
293
betab=betab*ut**(wexp-1.0_dp)
294
END IF
295
END IF
296
297
VariableValues(Permutation(NodeIndexes(1:n))) = VariableValues(Permutation(NodeIndexes(1:n))) &
298
+ betab*NodalGrad(1:n)
299
300
End DO ! on IPs
301
302
End do ! on elements
303
304
Return
305
306
!------------------------------------------------------------------------------
307
END SUBROUTINE AdjointStokes_GradientBetaSolver
308
!------------------------------------------------------------------------------
309
310
311
312