Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/elmerice/Solvers/ForceToStress.F90
3204 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: Olivier Gagliardini, Ga¨el Durand, Mondher Chekki
26
! * Email:
27
! * Web: http://elmerice.elmerfem.org
28
! *
29
! * Original Date:
30
! * Modify on 15/12/2018: Add support to Parallel Solver
31
32
! ****************************************************************************/
33
! -----------------------------------------------------------------------
34
!> Solver to go from a Force (or Debit) to Stress (or Flux) SDOFs = 1
35
RECURSIVE SUBROUTINE ForceToStress( Model,Solver,dt,TransientSimulation )
36
!------------------------------------------------------------------------------
37
38
USE DefUtils
39
USE ElmerIceUtils
40
41
IMPLICIT NONE
42
43
!------------------------------------------------------------------------------
44
!******************************************************************************
45
!
46
! Solve stress equations for one timestep
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 equation solver options
55
!
56
! REAL(KIND=dp) :: dt,
57
! INPUT: Timestep size for time dependent simulations (NOTE: Not used
58
! currently)
59
!
60
!******************************************************************************
61
62
TYPE(Model_t) :: Model
63
TYPE(Solver_t), TARGET :: Solver
64
65
LOGICAL :: TransientSimulation
66
REAL(KIND=dp) :: dt
67
!------------------------------------------------------------------------------
68
! Local variables
69
!------------------------------------------------------------------------------
70
TYPE(Solver_t), POINTER :: PSolver
71
72
TYPE(Matrix_t), POINTER :: StiffMatrix
73
74
INTEGER :: i, j, k, l, n, t, iter, NDeg, STDOFs, LocalNodes, istat
75
INTEGER :: dim
76
77
TYPE(ValueList_t),POINTER :: Material, BC
78
TYPE(Nodes_t) :: ElementNodes
79
TYPE(Element_t),POINTER :: CurrentElement
80
TYPE(Element_t),POINTER :: Element
81
82
REAL(KIND=dp) :: RelativeChange, UNorm, PrevUNorm, s
83
84
LOGICAL :: stat, CSymmetry, IsPeriodicBC, Found
85
86
INTEGER :: NewtonIter, NonlinearIter, bc_Id
87
88
TYPE(Variable_t), POINTER :: StressSol, ForceSol
89
90
REAL(KIND=dp), POINTER :: Stress(:), ForceValues(:), &
91
ForceVector(:)
92
93
INTEGER, POINTER :: StressPerm(:), ForcePerm(:), NodeIndexes(:)
94
95
LOGICAL :: GotIt, AllocationsDone = .FALSE.,UnFoundFatal=.TRUE.
96
97
REAL(KIND=dp), ALLOCATABLE:: LocalMassMatrix(:,:), &
98
LocalStiffMatrix(:,:), LocalForce(:), &
99
NodalForce(:)
100
101
CHARACTER(LEN=MAX_NAME_LEN) :: SolverName, InputVariableName
102
REAL(KIND=dp) :: at, at0
103
INTEGER :: nlen
104
CHARACTER(LEN=MAX_NAME_LEN) :: VarName
105
REAL(KIND=dp) , ALLOCATABLE :: ForceValues_tmp(:)
106
107
!------------------------------------------------------------------------------
108
SAVE LocalMassMatrix, LocalStiffMatrix, LocalForce, &
109
ElementNodes, AllocationsDone
110
SAVE NodalForce, dim
111
112
!------------------------------------------------------------------------------
113
! Get Force variable
114
!------------------------------------------------------------------------------
115
SolverName = 'ForceToStress'
116
117
InputVariableName = GetString( Solver % Values, 'Force Variable Name', GotIt )
118
IF (.NOT.GotIt) THEN
119
InputVariableName = 'Force'
120
CALL INFO(SolverName,'Force Variable Name sets to Force',Level=4)
121
END IF
122
123
ForceSol => VariableGet( Solver % Mesh % Variables, InputVariableName,UnFoundFatal=UnFoundFatal)
124
ForcePerm => ForceSol % Perm
125
ForceValues => ForceSol % Values
126
127
!------------------------------------------------------------------------------
128
! Allocate temporary storage
129
!------------------------------------------------------------------------------
130
ALLOCATE( ForceValues_tmp(SIZE(ForceValues)), STAT=istat )
131
IF ( istat /= 0 ) THEN
132
CALL Fatal( SolverName, 'Memory allocation error.' )
133
END IF
134
!------------------------------------------------------------------------------
135
! Get variables needed for solution
136
!------------------------------------------------------------------------------
137
IF ( .NOT. ASSOCIATED( Solver % Matrix ) ) RETURN
138
139
StressSol => Solver % Variable
140
StressPerm => StressSol % Perm
141
STDOFs = StressSol % DOFs
142
Stress => StressSol % Values
143
144
LocalNodes = COUNT( StressPerm > 0 )
145
IF ( LocalNodes <= 0 ) RETURN
146
147
148
StiffMatrix => Solver % Matrix
149
ForceVector => StiffMatrix % RHS
150
UNorm = Solver % Variable % Norm
151
152
!------------------------------------------------------------------------------
153
! Allocate some permanent storage, this is done first time only
154
!------------------------------------------------------------------------------
155
IF ( .NOT. AllocationsDone .OR. Solver % MeshChanged) THEN
156
N = Model % MaxElementNodes
157
dim = CoordinateSystemDimension()
158
159
IF ( AllocationsDone ) THEN
160
DEALLOCATE( ElementNodes % x, &
161
ElementNodes % y, &
162
ElementNodes % z, &
163
NodalForce, &
164
LocalMassMatrix, &
165
LocalStiffMatrix, &
166
LocalForce )
167
END IF
168
169
ALLOCATE( ElementNodes % x( N ), &
170
ElementNodes % y( N ), &
171
ElementNodes % z( N ), &
172
NodalForce(N ), &
173
LocalMassMatrix( 2*STDOFs*N,2*STDOFs*N ), &
174
LocalStiffMatrix( 2*STDOFs*N,2*STDOFs*N ), &
175
LocalForce( 2*STDOFs*N ), STAT=istat )
176
177
IF ( istat /= 0 ) THEN
178
CALL Fatal( SolverName, 'Memory allocation error.' )
179
END IF
180
!------------------------------------------------------------------------------
181
AllocationsDone = .TRUE.
182
END IF
183
184
!------------------------------------------------------------------------------
185
! Update Force solution on Parallel Partitions
186
!------------------------------------------------------------------------------
187
VarName=GetVarName(Solver % Variable)
188
189
CALL UpdatePartitionWeight(Model, Solver, VarName, ForceSol, ForceValues_tmp)
190
!------------------------------------------------------------------------------
191
NonlinearIter = 1
192
DO iter=1,NonlinearIter
193
194
at = CPUTime()
195
at0 = RealTime()
196
197
CALL Info( SolverName, 'Starting assembly...',Level=4 )
198
199
!------------------------------------------------------------------------------
200
CALL DefaultInitialize()
201
!------------------------------------------------------------------------------
202
DO t=1,Solver % NumberOFActiveElements
203
204
IF ( RealTime() - at0 > 1.0 ) THEN
205
WRITE(Message,'(a,i3,a)' ) ' Assembly: ', &
206
INT(100.0 - 100.0 * (Solver % NumberOfActiveElements-t) / &
207
(1.0*Solver % NumberOfActiveElements)), ' % done'
208
CALL Info( SolverName, Message, Level=5 )
209
at0 = RealTime()
210
END IF
211
212
CurrentElement => GetActiveElement(t)
213
n = GetElementNOFNodes()
214
NodeIndexes => CurrentElement % NodeIndexes
215
216
ElementNodes % x(1:n) = Model % Nodes % x(NodeIndexes(1:n))
217
ElementNodes % y(1:n) = Model % Nodes % y(NodeIndexes(1:n))
218
ElementNodes % z(1:n) = Model % Nodes % z(NodeIndexes(1:n))
219
220
Material => GetMaterial()
221
222
!------------------------------------------------------------------------------
223
! Get element local stiffness & mass matrices
224
!------------------------------------------------------------------------------
225
226
CALL LocalMatrix( LocalMassMatrix, LocalStiffMatrix, &
227
CurrentElement, n, ElementNodes )
228
229
!------------------------------------------------------------------------------
230
! Update global matrices from local matrices
231
!------------------------------------------------------------------------------
232
CALL DefaultUpdateEquations( LocalStiffMatrix, LocalForce )
233
234
END DO
235
236
DO i=1, Model % Mesh % NumberOfNodes
237
IF (StressPerm(i)>0) THEN
238
ForceVector(StressPerm(i)) = ForceValues_tmp(ForcePerm(i))
239
END IF
240
END DO
241
242
!------------------------------------------------------------------------------
243
! Deallocate temporary storage
244
!------------------------------------------------------------------------------
245
DEALLOCATE(ForceValues_tmp)
246
!------------------------------------------------------------------------------
247
! Special traitment for nodes belonging in periodic boundary (F = 0)
248
!------------------------------------------------------------------------------
249
CALL SetZeroAtPeriodicNodes(Model, Solver, VarName, ForceVector, ForcePerm, StressPerm)
250
251
CALL Info( SolverName, 'Assembly done', Level=4 )
252
253
CALL DefaultFinishAssembly()
254
255
!------------------------------------------------------------------------------
256
! Dirichlet boundary conditions
257
!------------------------------------------------------------------------------
258
! Only needed to account for periodic BC
259
!
260
CALL DefaultDirichletBCs()
261
262
!------------------------------------------------------------------------------
263
264
CALL Info( SolverName, 'Set boundaries done', Level=4 )
265
266
!------------------------------------------------------------------------------
267
! Solve the system and check for convergence
268
!------------------------------------------------------------------------------
269
PrevUNorm = UNorm
270
271
UNorm = DefaultSolve()
272
273
unorm = 0
274
n = Solver % Variable % DOFs
275
DO i=1,n-1
276
unorm = unorm + SUM( solver % variable % values(i::n)**2 )
277
END DO
278
279
unorm = SQRT( unorm )
280
281
solver % variable % norm = unorm
282
283
IF ( PrevUNorm + UNorm /= 0.0d0 ) THEN
284
RelativeChange = 2.0d0 * ABS( PrevUNorm - UNorm) / ( PrevUnorm + UNorm)
285
ELSE
286
RelativeChange = 0.0d0
287
END IF
288
289
WRITE( Message, * ) 'Result Norm : ',UNorm, PrevUNorm
290
CALL Info( SolverName, Message, Level=4 )
291
WRITE( Message, * ) 'Relative Change : ',RelativeChange
292
CALL Info( SolverName, Message, Level=4 )
293
294
295
!------------------------------------------------------------------------------
296
END DO ! of nonlinear iter
297
!------------------------------------------------------------------------------
298
299
300
CONTAINS
301
302
303
!------------------------------------------------------------------------------
304
SUBROUTINE LocalMatrix( MassMatrix, StiffMatrix, &
305
Element, n, Nodes )
306
307
!------------------------------------------------------------------------------
308
309
REAL(KIND=dp) :: StiffMatrix(:,:), MassMatrix(:,:)
310
TYPE(Nodes_t) :: Nodes
311
TYPE(Element_t) :: Element
312
INTEGER :: n
313
!------------------------------------------------------------------------------
314
!
315
REAL(KIND=dp) :: Basis(2*n), ddBasisddx(1,1,1)
316
REAL(KIND=dp) :: dBasisdx(2*n,3), detJ
317
318
REAL(KIND=dp) :: LGrad(3,3), SR(3,3), Li(9)
319
320
INTEGER :: i, j, k, p, q, t, dim, cc
321
322
REAL(KIND=dp) :: s, u, v, w, Radius
323
324
TYPE(GaussIntegrationPoints_t), TARGET :: IntegStuff
325
326
INTEGER :: N_Integ
327
328
REAL(KIND=dp), DIMENSION(:), POINTER :: U_Integ, V_Integ, W_Integ, S_Integ
329
330
LOGICAL :: stat, CSymmetry
331
332
!------------------------------------------------------------------------------
333
334
StiffMatrix = 0.0D0
335
MassMatrix = 0.0D0
336
337
IntegStuff = GaussPoints( Element )
338
339
U_Integ => IntegStuff % u
340
V_Integ => IntegStuff % v
341
W_Integ => IntegStuff % w
342
S_Integ => IntegStuff % s
343
N_Integ = IntegStuff % n
344
!
345
! Now we start integrating
346
!
347
DO t=1,N_Integ
348
349
u = U_Integ(t)
350
v = V_Integ(t)
351
w = W_Integ(t)
352
353
!------------------------------------------------------------------------------
354
! Basis function values & derivatives at the integration point
355
!------------------------------------------------------------------------------
356
stat = ElementInfo(Element,Nodes,u,v,w,detJ, &
357
Basis,dBasisdx,ddBasisddx,.FALSE.,.FALSE.)
358
359
360
s = detJ * S_Integ(t)
361
362
363
Radius = SUM( Nodes % x(1:n) * Basis(1:n) )
364
CSymmetry = CurrentCoordinateSystem() == AxisSymmetric
365
IF ( CSymmetry ) s = s * Radius
366
367
368
DO p=1,n
369
DO q=1,n
370
StiffMatrix(p,q) = &
371
StiffMatrix(p,q) + s*Basis(q)*Basis(p)
372
END DO
373
END DO
374
END DO
375
376
!------------------------------------------------------------------------------
377
END SUBROUTINE LocalMatrix
378
!------------------------------------------------------------------------------
379
380
!------------------------------------------------------------------------------
381
END SUBROUTINE ForceToStress
382
!------------------------------------------------------------------------------
383
384