1
!/*****************************************************************************/
3
! * Elmer, A Finite Element Software for Multiphysical Problems
5
! * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
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.
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.
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.
22
! *****************************************************************************/
24
!/******************************************************************************
26
! * Module for computing fluxes of Poisson type of equations
28
! ******************************************************************************
30
! * Authors: Peter Rļæ½back, Juha Ruokolainen
31
! * Email: Peter.Raback@csc.fi
32
! * Web: http://www.csc.fi/elmer
33
! * Address: CSC - IT Center for Science Ltd.
35
! * 02101 Espoo, Finland
37
! * Original Date: 20.06.2007
39
! *****************************************************************************/
41
!------------------------------------------------------------------------------
42
SUBROUTINE FluxSolver_Init( Model,Solver,dt,Transient )
43
!------------------------------------------------------------------------------
46
TYPE(Model_t) :: Model
47
TYPE(Solver_t) :: Solver
50
!------------------------------------------------------------------------------
51
TYPE(ValueList_t), POINTER :: SolverParams
53
!------------------------------------------------------------------------------
54
SolverParams => GetSolverParams()
55
dim = CoordinateSystemDimension()
57
IF ( .NOT. ListCheckPresent( SolverParams,'Variable') ) THEN
58
CALL ListAddInteger( SolverParams, 'Variable DOFs', 1 )
59
IF(ListCheckPresent(SolverParams,'Flux Component')) THEN
60
CALL ListAddString( SolverParams,'Variable','Flux' )
62
CALL ListAddString( SolverParams, 'Variable','-nooutput flux_temp' )
63
CALL ListAddString(SolverParams, 'Flux Result Variable','F')
65
CALL ListAddString(SolverParams, 'Exported Variable 1','F[Flux:2]')
66
ELSE IF(dim == 3) THEN
67
CALL ListAddString(SolverParams, 'Exported Variable 1','F[Flux:3]')
69
CALL Fatal('VortictySolver_init','Flux computation makes sense only in 2D and 3D')
73
CALL ListAddInteger( SolverParams, 'Time derivative order', 0 )
75
! Add linear system defaults: cg+diagonal
76
IF(.NOT. ListCheckPresent(SolverParams,'Linear System Solver')) &
77
CALL ListAddString(SolverParams,'Linear System Solver','Iterative')
78
IF(.NOT. ListCheckPresent(SolverParams,'Linear System Iterative Method')) &
79
CALL ListAddString(SolverParams,'Linear System Iterative Method','cg')
80
IF(.NOT. ListCheckPresent(SolverParams,'Linear System Preconditioning')) &
81
CALL ListAddString(SolverParams,'Linear System Preconditioning','diagonal')
82
IF(.NOT. ListCheckPresent(SolverParams,'Linear System Max Iterations')) &
83
CALL ListAddInteger(SolverParams,'Linear System Max Iterations',500)
84
IF(.NOT. ListCheckPresent(SolverParams,'Linear System Residual Output')) &
85
CALL ListAddInteger(SolverParams,'Linear System Residual Output',10)
86
IF(.NOT. ListCheckPresent(SolverParams,'Linear System Convergence Tolerance')) &
87
CALL ListAddConstReal(SolverParams,'Linear System Convergence Tolerance',1.0e-10_dp)
89
!------------------------------------------------------------------------------
90
END SUBROUTINE FluxSolver_Init
91
!------------------------------------------------------------------------------
96
!------------------------------------------------------------------------------
97
SUBROUTINE FluxSolver( Model,Solver,dt,Transient )
98
!------------------------------------------------------------------------------
100
USE CoordinateSystems
104
!------------------------------------------------------------------------------
105
!******************************************************************************
107
! Solve stress equations for one timestep
111
! TYPE(Model_t) :: Model,
112
! INPUT: All model information (mesh,materials,BCs,etc...)
114
! TYPE(Solver_t) :: Solver
115
! INPUT: Linear equation solver options
117
! REAL(KIND=dp) :: dt,
118
! INPUT: Timestep size for time dependent simulations (NOTE: Not used
121
!******************************************************************************
123
TYPE(Model_t) :: Model
124
TYPE(Solver_t), TARGET :: Solver
127
!------------------------------------------------------------------------------
129
!------------------------------------------------------------------------------
130
TYPE(ValueList_t),POINTER :: SolverParams
131
CHARACTER(LEN=MAX_NAME_LEN) :: VarName, CondName
132
INTEGER :: i,j,dim,DOFs,ActiveDir
133
LOGICAL :: ConstantBulkMatrix, ConstantBulkMatrixInUse, CSymmetry
134
LOGICAL :: GotIt, Visited = .FALSE., DirMask(3)
135
REAL(KIND=dp) :: Unorm, Totnorm
136
REAL(KIND=dp), POINTER :: ForceVector(:,:), SaveRHS(:)
137
REAL(KIND=dp) :: at0,at1,at2,CPUTime,RealTime
138
TYPE(Variable_t), POINTER :: FluxSol
143
CALL Info( 'FluxSolver', '-------------------------------------',Level=4 )
144
CALL Info( 'FluxSolver','Computing the flux',Level=4 )
145
CALL Info( 'FluxSolver', '-------------------------------------',Level=4 )
147
dim = CoordinateSystemDimension()
148
!------------------------------------------------------------------------------
149
! Get variables needed for solution
150
!------------------------------------------------------------------------------
151
IF ( .NOT. ASSOCIATED( Solver % Matrix ) ) RETURN
152
IF ( COUNT( Solver % Variable % Perm > 0 ) <= 0 ) RETURN
154
SolverParams => GetSolverParams()
156
!-------------------------------------------------------------------------------
157
! If only one component is used use the scalar equation, otherwise use an
158
! auxiliary variable to store all the dimensions
159
!-------------------------------------------------------------------------------
160
ActiveDir = GetInteger( SolverParams, 'Flux Component', GotIt)
164
VarName = GetString(SolverParams,'Flux Result Variable',GotIt )
165
IF(.NOT. gotIt) VarName = 'Flux'
166
FluxSol => VariableGet( Solver % Mesh % Variables, VarName )
167
IF(ASSOCIATED(FluxSol)) THEN
168
Dofs = FluxSol % DOFs
170
CALL Fatal('FluxSolver','The flux should have DOFs equal to DIM')
173
CALL Fatal('FluxSolver','Flux Result Variable is missing: '//TRIM(VarName))
178
CSymmetry = CurrentCoordinateSystem() == AxisSymmetric .OR. &
179
CurrentCoordinateSystem() == CylindricSymmetric
181
VarName = GetString(SolverParams,'Flux Variable',GotIt )
182
IF(.NOT. gotIt) VarName = TRIM('Temperature')
184
CondName = ListGetString(SolverParams,'Flux Coefficient',GotIt )
185
IF(.NOT. gotIt) CondName = TRIM('Heat Conductivity')
189
ConstantBulkMatrix = GetLogical( SolverParams, 'Constant Bulk Matrix', GotIt )
190
ConstantBulkMatrixInUse = ConstantBulkMatrix .AND. &
191
ASSOCIATED(Solver % Matrix % BulkValues)
193
IF ( ConstantBulkMatrixInUse ) THEN
194
Solver % Matrix % Values = Solver % Matrix % BulkValues
195
Solver % Matrix % rhs = 0.0_dp
197
CALL DefaultInitialize()
201
ALLOCATE(ForceVector(Dofs-1,SIZE(Solver % Matrix % RHS)))
203
SaveRHS => Solver % Matrix % RHS
207
CALL DefaultFinishAssembly()
210
WRITE(Message,* ) 'Assembly Time: ',at1-at0
211
CALL Info( 'FluxSolver', Message, Level=5 )
213
!------------------------------------------------------------------------------
219
Solver % Matrix % RHS => SaveRHS
221
Solver % Matrix % RHS => ForceVector(i-1,:)
223
UNorm = DefaultSolve()
224
TotNorm = TotNorm + Unorm ** 2
225
DO j=1,Solver % Matrix % NumberOfRows
226
FluxSol % Values(DOFs*(j-1)+i) = Solver % Variable % Values(j)
229
DEALLOCATE( ForceVector )
230
Solver % Matrix % RHS => SaveRHS
231
TotNorm = SQRT(TotNorm)
232
Solver % Variable % Norm = Totnorm
234
TotNorm = DefaultSolve()
236
!------------------------------------------------------------------------------
239
WRITE(Message,* ) 'Solution Time: ',at2-at1
240
CALL Info( 'FluxSolver', Message, Level=5 )
242
WRITE( Message, * ) 'Result Norm: ',TotNorm
243
CALL Info( 'FluxSolver', Message, Level=4 )
248
!------------------------------------------------------------------------------
249
SUBROUTINE BulkAssembly()
250
!------------------------------------------------------------------------------
252
INTEGER :: elem,t,i,j,p,q,n,nd, Rank
253
REAL(KIND=dp), ALLOCATABLE :: STIFF(:,:), FORCE(:,:)
254
TYPE(GaussIntegrationPoints_t), TARGET :: IntegStuff
255
TYPE(Nodes_t) :: Nodes
256
TYPE(Element_t), POINTER :: Element
257
REAL(KIND=dp) :: weight,grad(3),C(3,3),coeff,detJ
258
REAL(KIND=dp), ALLOCATABLE :: Basis(:), dBasisdx(:,:)
259
REAL(KIND=dp), ALLOCATABLE :: LocalPotential(:)
261
TYPE(ValueList_t), POINTER :: Material
262
REAL(KIND=dp), POINTER :: Conductivity(:,:,:)=>NULL()
264
SAVE Conductivity, Nodes
266
n = MAX( Solver % Mesh % MaxElementDOFs, Solver % Mesh % MaxElementNodes )
267
ALLOCATE( STIFF(n,n), FORCE(dim,n) )
268
ALLOCATE( LocalPotential(n), Basis(n), dBasisdx(n,3) )
270
DO elem = 1,Solver % NumberOFActiveElements
272
! Element information
273
! ---------------------
274
Element => GetActiveElement(elem)
275
CALL GetElementNodes( Nodes )
276
nd = GetElementNOFDOFs()
277
n = GetElementNOFNodes()
279
CALL GetRealArray( GetMaterial(), Conductivity, CondName, Found )
281
IF ( Found ) Rank = GetTensorRank(Conductivity)
282
CALL GetScalarLocalSolution( LocalPotential, VarName )
284
! Integrate local stresses:
285
! -------------------------
286
IntegStuff = GaussPoints( Element )
295
DO t=1,IntegStuff % n
296
Found = ElementInfo( Element, Nodes, IntegStuff % u(t), &
297
IntegStuff % v(t), IntegStuff % w(t), detJ, Basis, dBasisdx )
299
Weight = IntegStuff % s(t) * detJ
300
IF ( CSymmetry ) Weight = Weight * SUM( Basis(1:n) * Nodes % x(1:n) )
302
IF ( .NOT. ConstantBulkMatrixInUse ) THEN
305
STIFF(p,q) = STIFF(p,q) + Weight * Basis(q) * Basis(p)
310
Grad(1:dim) = MATMUL( LocalPotential(1:nd), dBasisdx(1:nd,1:dim) )
316
C(i,i) = SUM( Basis(1:n) * Conductivity(1,1,1:n) )
320
C(i,i) = SUM( Basis(1:n) * Conductivity(i,1,1:n) )
325
C(i,j) = SUM( Basis(1:n) * Conductivity(i,j,1:n) )
331
Coeff = Weight * SUM( C(ActiveDir,1:dim) * Grad(1:dim) )
332
FORCE(1,1:nd) = FORCE(1,1:nd) - Coeff*Basis(1:nd)
335
Coeff = Weight * SUM( C(i,1:dim) * Grad(1:dim) )
336
FORCE(i,1:nd) = FORCE(i,1:nd) - Coeff*Basis(1:nd)
341
!------------------------------------------------------------------------------
342
! Update global matrices from local matrices
343
!------------------------------------------------------------------------------
344
IF ( .NOT. ConstantBulkMatrixInUse ) THEN
345
IF(Dofs > 1) Solver % Matrix % RHS => SaveRHS
346
CALL DefaultUpdateEquations( STIFF, FORCE(1,1:nd), &
347
BulkUpdate=ConstantBulkMatrix )
349
CALL DefaultUpdateForce( FORCE(1,1:nd) )
353
Solver % Matrix % RHS => ForceVector(i-1,:)
354
CALL DefaultUpdateForce( FORCE(i,1:nd) )
358
DEALLOCATE( LocalPotential, STIFF, FORCE, Basis, dBasisdx )
359
!------------------------------------------------------------------------------
360
END SUBROUTINE BulkAssembly
361
!------------------------------------------------------------------------------
364
!------------------------------------------------------------------------------
365
FUNCTION GetTensorRank( Tensor ) RESULT ( Rank )
366
!------------------------------------------------------------------------------
367
REAL(KIND=dp), POINTER :: Tensor(:,:,:)
370
IF ( SIZE(Tensor,1) == 1 ) THEN
372
ELSE IF ( SIZE(Tensor,2) == 1 ) THEN
377
!-----------------------------------------------------------------------------
378
END FUNCTION GetTensorRank
379
!------------------------------------------------------------------------------
382
!------------------------------------------------------------------------------
383
END SUBROUTINE FluxSolver
384
!------------------------------------------------------------------------------