Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/fem/tests/BDM2D/ComputeError.F90
3206 views
1
!/*****************************************************************************/
2
! *
3
! * Elmer, A Finite Element Software for Multiphysical Problems
4
! *
5
! * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland
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
! * Compute the L2 errors of the mixed solution of the Poisson equation
25
! * in a special case.
26
! *
27
! *
28
! * Authors: Mika Malinen
29
! * Email: [email protected]
30
! * Web: http://www.csc.fi/elmer
31
! * Address: CSC - IT Center for Science Ltd.
32
! * Keilaranta 14
33
! * 02101 Espoo, Finland
34
! *
35
! * Original Date: March 12, 2019
36
! *
37
!******************************************************************************
38
39
!------------------------------------------------------------------------------
40
SUBROUTINE IntegrateError(Model, Solver, dt, TransientSimulation)
41
!------------------------------------------------------------------------------
42
USE DefUtils
43
IMPLICIT NONE
44
!------------------------------------------------------------------------------
45
TYPE(Model_t) :: Model
46
TYPE(Solver_t) :: Solver
47
REAL(KIND=dp) :: dt
48
LOGICAL :: TransientSimulation
49
!------------------------------------------------------------------------------
50
! Local variables
51
!------------------------------------------------------------------------------
52
TYPE(ValueList_t), POINTER :: SolverPars, TargetSolverPars
53
TYPE(Solver_t), POINTER :: TargetSolver
54
TYPE(Mesh_t), POINTER :: Mesh
55
TYPE(Element_t),POINTER :: Element
56
57
LOGICAL :: AllocationsDone = .FALSE., Found, SecondFamily
58
59
CHARACTER(LEN=MAX_NAME_LEN) :: TargetEq, Eq
60
61
INTEGER, ALLOCATABLE :: Indices(:)
62
INTEGER :: i, istat, nlen
63
INTEGER :: n, nb, np, nd, t, dim
64
65
REAL(KIND=dp), ALLOCATABLE :: SolDOFs(:)
66
REAL(KIND=dp) :: PresErr, FluxErr, EK(2), SolNorm, FluxNorm
67
68
SAVE SolDOFs, Indices, AllocationsDone
69
!------------------------------------------------------------------------------
70
SolverPars => GetSolverParams()
71
72
!
73
! Get pointer to the solver the variable of which is used to integrate
74
! the error:
75
!
76
77
TargetEq = ListGetString(SolverPars, 'Target Equation', UnfoundFatal=.TRUE.)
78
nlen = LEN_TRIM(TargetEq)
79
TargetSolver => NULL()
80
DO i=1,Model % NumberOfSolvers
81
Eq = ListGetString(Model % Solvers(i) % Values, 'Equation', Found)
82
IF (Found) THEN
83
IF (nlen == LEN_TRIM(Eq)) THEN
84
IF (TargetEq(1:nlen) == Eq(1:nlen)) TargetSolver => Model % Solvers(i)
85
END IF
86
END IF
87
END DO
88
IF (.NOT. ASSOCIATED(TargetSolver)) CALL Fatal('ComputeError', &
89
'Target Equation does not exist')
90
91
TargetSolverPars => GetSolverParams(TargetSolver)
92
SecondFamily = GetLogical(TargetSolverPars, 'Second Kind Basis', Found)
93
dim = CoordinateSystemDimension()
94
95
96
!Allocate some permanent storage, this is done first time only:
97
!--------------------------------------------------------------
98
Mesh => GetMesh()
99
IF ( .NOT. AllocationsDone ) THEN
100
N = Mesh % MaxElementDOFs
101
ALLOCATE(SolDOFs(N), Indices(N), STAT=istat)
102
IF (istat /= 0) THEN
103
CALL Fatal( 'ComputeError', 'Memory allocation error.' )
104
END IF
105
AllocationsDone = .TRUE.
106
END IF
107
108
PresErr = 0.0d0
109
FluxErr = 0.0d0
110
SolNorm = 0.0d0
111
FluxNorm = 0.0d0
112
DO t=1,TargetSolver % NumberOfActiveElements
113
114
Element => GetActiveElement(t, TargetSolver)
115
n = GetElementNOFNodes(Element)
116
nd = GetElementDOFs(Indices, Element, TargetSolver)
117
nb = size(Element % BubbleIndexes(:))
118
119
np = n * TargetSolver % Def_Dofs(GetElementFamily(Element), &
120
Element % BodyId, 1)
121
122
DO i=1,nd
123
SolDOFs(i) = TargetSolver % Variable % Values(TargetSolver % Variable % &
124
Perm(Indices(i)))
125
END DO
126
127
CALL ElementwiseError(SolDofs, Element, n, nd, nb, np, dim, EK, SolNorm, &
128
FluxNorm, SecondFamily)
129
130
PresErr = PresErr + EK(1)
131
FluxErr = FluxErr + EK(2)
132
133
END DO
134
WRITE (*, '(A,E16.8)') 'L2 Scalar Error = ', SQRT(ParallelReduction(PresErr))/SQRT(ParallelReduction(SolNorm))
135
WRITE (*, '(A,E16.8)') 'L2 Flux Error =', SQRT(ParallelReduction(FluxErr))/SQRT(ParallelReduction(FluxNorm))
136
137
CONTAINS
138
139
!------------------------------------------------------------------------------
140
SUBROUTINE ElementwiseError(SolDOFs, Element, n, nd, nb, np, dim, EK, &
141
SolNorm, FluxNorm, SecondFamily)
142
!------------------------------------------------------------------------------
143
REAL(KIND=dp) :: SolDOFs(:)
144
TYPE(Element_t), POINTER :: Element
145
INTEGER :: n, nd, nb, np, dim
146
REAL(KIND=dp) :: EK(2), SolNorm, FluxNorm
147
LOGICAL :: SecondFamily
148
!------------------------------------------------------------------
149
TYPE(Nodes_t), SAVE :: Nodes
150
TYPE(GaussIntegrationPoints_t) :: IP
151
INTEGER :: i, p, t
152
LOGICAL :: Stat
153
REAL(KIND=dp) :: FaceBasis(nd,3), DivFaceBasis(nd), Basis(nd)
154
REAL(KIND=dp) :: uq, vq, wq, sq
155
REAL(KIND=dp) :: xq, yq, zq, DetJ, sol, gradsol(dim), fluxsol(dim)
156
157
158
!---------------------------------------------------------------------------
159
IF (nb /= 1) CALL Fatal('ComputeError', 'One bubble DOF assumed')
160
161
CALL GetElementNodes( Nodes )
162
163
EK = 0.0d0
164
165
SELECT CASE( GetElementFamily(Element) )
166
CASE(3)
167
IP = GaussPointsTriangle(3, PReferenceElement=.TRUE.)
168
CASE(5)
169
IP = GaussPointsTetra(4, PReferenceElement=.TRUE.)
170
CASE DEFAULT
171
CALL Fatal('ComputeError', 'A simplicial mesh assumed currently')
172
END SELECT
173
174
DO t=1,IP % n
175
stat = FaceElementInfo(Element, Nodes, IP % U(t), IP % V(t), &
176
IP % W(t), detF=detJ, Basis=Basis, FBasis=FaceBasis, &
177
DivFBasis=DivFaceBasis, BDM = SecondFamily, ApplyPiolaTransform=.TRUE.)
178
179
xq = SUM( Nodes % x(1:n) * Basis(1:n) )
180
yq = SUM( Nodes % y(1:n) * Basis(1:n) )
181
zq = SUM( Nodes % z(1:n) * Basis(1:n) )
182
183
sol = 16.0d0*(xq-xq**2) * (yq-yq**2)
184
gradsol(1) = 16.0d0 * (1.0d0 -2.0d0*xq) * (yq-yq**2)
185
gradsol(2) = 16.0d0 * (1.0d0 -2.0d0*yq) * (xq-xq**2)
186
187
! For computing the error of the scalar field:
188
SolNorm = SolNorm + sol**2 * detJ * IP % s(t)
189
EK(1) = EK(1) + (sol - SolDOFs(nd))**2 * detJ * IP % s(t)
190
191
192
FluxNorm = FluxNorm + SUM( gradsol(1:dim)*gradsol(1:dim) ) * detJ * IP % s(t)
193
194
FluxSol = 0.0d0
195
DO p = 1,nd-np-nb
196
i = np + p
197
FluxSol(1:dim) = FluxSol(1:dim) + FaceBasis(p,1:dim) * SolDOFs(i)
198
END DO
199
200
EK(2) = EK(2) + SUM( (gradsol(1:dim) - fluxsol(1:dim))**2 ) * &
201
detJ * IP % s(t)
202
203
END DO
204
!------------------------------------------------------------------------------
205
END SUBROUTINE ElementwiseError
206
!-----------------------------------------------------------------------------
207
208
209
!------------------------------------------------------------------------------
210
END SUBROUTINE IntegrateError
211
!------------------------------------------------------------------------------
212
213