FE-Project
Loading...
Searching...
No Matches
scale_meshfield_analysis_numerror_base.F90
Go to the documentation of this file.
1!-------------------------------------------------------------------------------
2!> module FElib / Data / Statistics / numerical error
3!!
4!! @par Description
5!! This module provides a base class useful for evaluating numerical errors
6!!
7!! @author Yuta Kawai, Team SCALE
8!!
9!<
10!-------------------------------------------------------------------------------
11#include "scaleFElib.h"
13 !-----------------------------------------------------------------------------
14 !
15 !++ used modules
16 !
17 use scale_precision
18 use scale_io
19 use scale_prc, only: &
20 prc_ismaster, prc_abort
21 use scale_time_manager, only: &
22 time_nstep
23
30 use scale_mesh_base, only: meshbase
32
33 !-----------------------------------------------------------------------------
34 implicit none
35 private
36
37 !-----------------------------------------------------------------------------
38 !
39 !++ Public type & procedure
40 !
41
42 !> Derived type saving information for numerical error analysis
43 type, abstract, public :: meshfieldanalysisnumerrorinfobase
45
46 !> Base type for numerical error analysis of mesh field
48 integer :: var_num !< Number of variables to be analyzed
49 integer :: log_fid !< File ID for log output
50 integer :: log_step_interval !< Interval of time step for log output
51 integer :: log_rstep !< Remaining step for log output
52 logical :: output_error_first !< Flag for outputting error at the first time
53
54 class(meshbase), pointer :: mesh !< Pointer to an object of type MeshBase
55
56 integer :: polyordererrorcheck !< Polynomial order when evaluating numerical errors
57 integer :: intrp_np !< Number of interpolation points
58 integer :: ndim !< Number of dimensions
59 real(rp), allocatable :: intrpmat(:,:) !< Interpolation matrix for numerical error evaluation
60 real(rp), allocatable :: intw_intrp(:) !< Weights of integration for interpolation points
61 real(rp), allocatable :: epos_intrp(:,:) !< Positions of interpolation points
62
63 class(meshfieldanalysisnumerrorinfobase), pointer :: info !< Pointer to information for numerical error analysis
64 contains
65 procedure :: init_base => meshfield_analysis_numerror_base_init
66 generic :: init => init_base
67 procedure :: final => meshfield_analysis_numerror_base_final
68 procedure :: regist => meshfield_analysis_numerror_base_regist
69 procedure :: evaluate_base => meshfield_analysis_numerror_base_evaluate
70 !
71 procedure :: evaluate_error_lc => meshfield_analysis_numerror_base_evaluate_error_lc
72 procedure :: evaluate_covariance_lc => meshfield_analysis_numerror_base_evaluate_covariance_lc
74
75 !-----------------------------------------------------------------------------
76 !
77 !++ Public parameters & variables
78 !
79
80 !-----------------------------------------------------------------------------
81 !
82 !++ Private procedures & parameters & variables
83 !
84 abstract interface
85 subroutine evaluate_error_interface( this_, tsec, &
86 num_error_l1_lc_, num_error_l2_lc_, num_error_linf_lc_, &
87 numsol_mean, exactsol_mean )
88 import rp
90 class(meshfieldanalysisnumerrorbase), intent(in) :: this_
91 real(RP), intent(in) :: tsec
92 real(RP), intent(inout) :: num_error_l1_lc_(this_%var_num)
93 real(RP), intent(inout) :: num_error_l2_lc_(this_%var_num)
94 real(RP), intent(inout) :: num_error_linf_lc_(this_%var_num)
95 real(RP), intent(inout) :: numsol_mean(this_%var_num)
96 real(RP), intent(inout) :: exactsol_mean(this_%var_num)
97 end subroutine evaluate_error_interface
98
99 subroutine calc_covariance_interface( this_, tsec, &
100 cov_numsol_numsol_lc, cov_numsol_exactsol_lc, cov_exactsol_exactsol_lc, &
101 numsol_mean, exactsol_mean )
102 import rp
104 class(meshfieldanalysisnumerrorbase), intent(in) :: this_
105 real(RP), intent(in) :: tsec
106 real(RP), intent(inout) :: cov_numsol_numsol_lc(this_%var_num)
107 real(RP), intent(inout) :: cov_numsol_exactsol_lc(this_%var_num)
108 real(RP), intent(inout) :: cov_exactsol_exactsol_lc(this_%var_num)
109 real(RP), intent(in) :: numsol_mean(this_%var_num)
110 real(RP), intent(in) :: exactsol_mean(this_%var_num)
111 end subroutine calc_covariance_interface
112 end interface
113
114 private :: numerror_do_step
115
116 !-----------------------------------------------------------------------------
117 !
118 !++ Private parameters & variables
119 !
120
121contains
122
123 !-----------------------------------------------------------------------------
124 !> Initialize an object for numerical error analysis
125!OCL SERIAL
126 subroutine meshfield_analysis_numerror_base_init( this, &
127 porder_error_check, ndim, np, intrp_np, log_fname_base, log_step_interval, &
128 mesh, numerror_analysis_info )
129 implicit none
130 class(meshfieldanalysisnumerrorbase), intent(inout) :: this
131 integer, intent(in) :: porder_error_check !< Polynomial order when evaluating numerical errors
132 integer, intent(in) :: ndim !< Number of dimensions
133 integer, intent(in) :: np !< Number of nodes per element
134 integer, intent(in) :: intrp_np !< Number of interpolation points for numerical error evaluation
135 character(len=*), intent(in) :: log_fname_base !< Base name of log file for numerical error analysis
136 integer, intent(in) :: log_step_interval !< Interval of time step for log output
137 class(meshbase), intent(in), target :: mesh !< Mesh for numerical error analysis
138 class(meshfieldanalysisnumerrorinfobase), intent(in), target :: numerror_analysis_info !< Information for numerical error analysis
139
140 character(len=H_MID) :: fname
141 integer :: ierr
142 !---------------------------------------------------------------------------
143
144 this%var_num = 0
145
146 this%log_step_interval = log_step_interval
147 this%log_rstep = log_step_interval
148
149 this%output_error_first = .true.
150
151 !--
152 if ( prc_ismaster ) then
153 this%log_fid = io_get_available_fid()
154 fname = trim(log_fname_base)//".peall"
155 open( unit = this%log_fid, &
156 file = fname, &
157 form = 'formatted', &
158 iostat = ierr )
159 if ( ierr /= 0 ) then
160 log_error('MeshField_NumErrorAnalysis_Init',*) 'File open error! :', trim(fname)
161 call prc_abort
162 endif
163 end if
164
165 !--
166 this%PolyOrderErrorCheck = porder_error_check
167 this%intrp_np = intrp_np
168 this%ndim = ndim
169 allocate( this%IntrpMat(this%intrp_np,np) )
170 allocate( this%intw_intrp(this%intrp_np) )
171 allocate( this%epos_intrp(this%intrp_np,this%ndim) )
172
173 this%info => numerror_analysis_info
174 this%mesh => mesh
175 return
176 end subroutine meshfield_analysis_numerror_base_init
177
178 !-----------------------------------------------------------------------------
179 !> Finalize an object for numerical error analysis
180!OCL SERIAL
181 subroutine meshfield_analysis_numerror_base_final( this )
182 implicit none
183 class(meshfieldanalysisnumerrorbase), intent(inout) :: this
184 !---------------------------------------------------------------------------
185
186 deallocate( this%IntrpMat, this%intw_intrp, this%epos_intrp )
187
188 close( this%log_fid )
189 this%log_fid = -1
190
191 this%info => null()
192 this%mesh => null()
193 return
194 end subroutine meshfield_analysis_numerror_base_final
195
196 !> Register a variable for numerical error analysis
197!OCL SERIAL
198 subroutine meshfield_analysis_numerror_base_regist( this, varname, unit, varid )
199 implicit none
200 class(meshfieldanalysisnumerrorbase), intent(inout) :: this
201 character(len=*), intent(in) :: varname !< Name of variable to be analyzed
202 character(len=*), intent(in) :: unit !< Unit of variable to be analyzed
203 integer, intent(out) :: varid !< ID of variable to be analyzed
204 !---------------------------------------------------------------------------
205
206 this%var_num = this%var_num + 1
207 varid = this%var_num
208
209 if ( prc_ismaster ) then
210 write(this%log_fid,'(A25)',advance='no') 'L1_error ('//trim(varname)//')'
211 write(this%log_fid,'(A25)',advance='no') 'L2_error ('//trim(varname)//')'
212 write(this%log_fid,'(A25)',advance='no') 'Linf_error ('//trim(varname)//')'
213 write(this%log_fid,'(A25)',advance='no') 'Ediss ('//trim(varname)//')'
214 write(this%log_fid,'(A25)',advance='no') 'Edisp ('//trim(varname)//')'
215 end if
216 return
217 end subroutine meshfield_analysis_numerror_base_regist
218
219 !> Evaluate numerical errors
220!OCL SERIAL
221 subroutine meshfield_analysis_numerror_base_evaluate( &
222 this, tstep, tsec, dom_vol, evaluate_error, calc_covariance )
223 use mpi
224 use scale_prc, only: &
225 prc_local_comm_world
226 implicit none
227 class(meshfieldanalysisnumerrorbase), intent(inout) :: this
228 integer, intent(in) :: tstep
229 real(RP) :: tsec
230 real(RP), intent(in) :: dom_vol
231 procedure(evaluate_error_interface) :: evaluate_error
232 procedure(calc_covariance_interface) :: calc_covariance
233
234 logical :: do_check_numerror
235
236 integer, parameter :: SUM_BUF_L1_ID = 1
237 integer, parameter :: SUM_BUF_L2_ID = 2
238 integer, parameter :: SUM_BUF_MEAN_NUMSOL_ID = 3
239 integer, parameter :: SUM_BUF_MEAN_EXACTSOL_ID = 4
240 integer, parameter :: SUM_BUF_NUM = 4
241
242 real(RP) :: num_error_linf_lc(this%var_num)
243 real(RP) :: sum_buf_lc(this%var_num,SUM_BUF_NUM)
244 real(RP) :: num_error_linf(this%var_num)
245 real(RP) :: sum_buf(this%var_num,SUM_BUF_NUM)
246
247 real(RP) :: covariance_lc(this%var_num,3)
248 real(RP) :: covariance(this%var_num,3)
249 real(RP) :: Ediss(this%var_num), Edisp(this%var_num)
250
251 integer :: iv
252 integer :: ierr
253 !---------------------------------------------------------------------------
254
255 if ( this%var_num == 0 ) return
256
257 if ( this%output_error_first ) then
258 if ( prc_ismaster ) write(this%log_fid,*)
259 this%output_error_first = .false.
260 end if
261
262 do_check_numerror = numerror_do_step( this, tstep )
263 if ( .not. do_check_numerror ) then
264 !if ( PRC_ismaster .and. TIME_NOWSTEP == TIME_NSTEP ) close( NUMERROR_LOG_FID )
265 return
266 end if
267
268 !---
269 num_error_linf_lc(:) = 0.0_rp
270 sum_buf_lc(:,:) = 0.0_rp
271
272 call evaluate_error( this, tsec, &
273 sum_buf_lc(:,sum_buf_l1_id), sum_buf_lc(:,sum_buf_l2_id), num_error_linf_lc(:), &
274 sum_buf_lc(:,sum_buf_mean_numsol_id), sum_buf_lc(:,sum_buf_mean_exactsol_id) )
275
276 call mpi_allreduce( sum_buf_lc(:,:), sum_buf(:,:), &
277 this%var_num * sum_buf_num, &
278 mpi_double_precision, &
279 mpi_sum, &
280 prc_local_comm_world, &
281 ierr )
282 call mpi_allreduce( num_error_linf_lc(:), num_error_linf(:), &
283 this%var_num, &
284 mpi_double_precision, &
285 mpi_max, &
286 prc_local_comm_world, &
287 ierr )
288
289 sum_buf(:,sum_buf_mean_numsol_id) = sum_buf(:,sum_buf_mean_numsol_id) / dom_vol
290 sum_buf(:,sum_buf_mean_exactsol_id) = sum_buf(:,sum_buf_mean_exactsol_id) / dom_vol
291
292 !--
293 covariance_lc(:,:) = 0.0_rp
294
295 call calc_covariance( this, tsec, &
296 covariance_lc(:,1), covariance_lc(:,2), covariance_lc(:,3), &
297 sum_buf(:,sum_buf_mean_numsol_id), sum_buf(:,sum_buf_mean_exactsol_id) )
298
299 call mpi_allreduce( covariance_lc(:,:), covariance(:,:), &
300 this%var_num * 3, &
301 mpi_double_precision, &
302 mpi_sum, &
303 prc_local_comm_world, &
304 ierr )
305
306 if ( prc_ismaster ) then
307
308 ediss(:) = ( sqrt(covariance(:,1) / dom_vol) - sqrt(covariance(:,3) / dom_vol) )**2 &
309 + ( sum_buf(:,sum_buf_mean_numsol_id) - sum_buf(:,sum_buf_mean_exactsol_id) )**2
310
311 edisp(:) = 2.0_rp * ( sqrt( covariance(:,1) * covariance(:,3) ) &
312 - covariance(:,2) ) / dom_vol
313
314 write(this%log_fid,'(A,ES18.8)',advance='no') 'tsec=', tsec
315 do iv=1, this%var_num
316 write(this%log_fid,'(A,ES18.8)',advance='no') ' ', sum_buf(iv,sum_buf_l1_id) / dom_vol
317 write(this%log_fid,'(A,ES18.8)',advance='no') ' ', sqrt(sum_buf(iv,sum_buf_l2_id) / dom_vol)
318 write(this%log_fid,'(A,ES18.8)',advance='no') ' ', num_error_linf(iv)
319 write(this%log_fid,'(A,ES18.8)',advance='no') ' ', ediss(iv)
320 write(this%log_fid,'(A,ES18.8)',advance='no') ' ', edisp(iv)
321 end do
322 write(this%log_fid,*)
323
324! if ( tstep > TIME_NSTEP ) close( NUMERROR_LOG_FID )
325 end if
326
327 return
328 end subroutine meshfield_analysis_numerror_base_evaluate
329
330 !> Evaluate numerical errors at local mesh level
331!OCL SERIAL
332 subroutine meshfield_analysis_numerror_base_evaluate_error_lc( base, &
333 num_error_l1_lc, num_error_l2_lc, num_error_linf_lc, &
334 numsol_mean_lc, exactsol_mean_lc, &
335 q, qexact, qexact_intrp, lcmesh, elem )
336 implicit none
337 class(meshfieldanalysisnumerrorbase), intent(in) :: base
338 class(localmeshbase), intent(in) :: lcmesh
339 class(elementbase), intent(in) :: elem
340 real(RP), intent(inout) :: num_error_l1_lc(base%var_num)
341 real(RP), intent(inout) :: num_error_l2_lc(base%var_num)
342 real(RP), intent(inout) :: num_error_linf_lc(base%var_num)
343 real(RP), intent(inout) :: numsol_mean_lc(base%var_num)
344 real(RP), intent(inout) :: exactsol_mean_lc(base%var_num)
345 real(RP), intent(in) :: q(elem%Np,lcmesh%Ne,base%var_num)
346 real(RP), intent(in) :: qexact(elem%Np,lcmesh%Ne,base%var_num)
347 real(RP), intent(in) :: qexact_intrp(base%intrp_np,lcmesh%Ne,base%var_num)
348
349 integer :: iv
350 integer :: ke
351
352 real(RP) :: linf_max_tmp(lcmesh%Ne,base%var_num)
353 real(RP) :: q_intrp(base%intrp_np)
354 real(RP) :: JGsqrtxIntw_intrp(base%intrp_np)
355 !---------------------------------------------------------------------------
356
357 do iv=1, base%var_num
358 !$omp parallel do private(ke, q_intrp, JGsqrtxIntw_intrp) reduction(+: num_error_l1_lc, num_error_l2_lc, numsol_mean_lc, exactsol_mean_lc )
359 do ke=lcmesh%NeS, lcmesh%NeE
360 q_intrp(:) = matmul( base%IntrpMat, q(:,ke,iv) )
361 jgsqrtxintw_intrp(:) = matmul( base%IntrpMat, lcmesh%J(:,ke) * lcmesh%Gsqrt(:,ke) )
362 jgsqrtxintw_intrp(:) = jgsqrtxintw_intrp(:) * base%intw_intrp(:)
363
364 num_error_l1_lc(iv) = num_error_l1_lc(iv) + sum( jgsqrtxintw_intrp(:) * abs( q_intrp(:) - qexact_intrp(:,ke,iv) ) )
365 num_error_l2_lc(iv) = num_error_l2_lc(iv) + sum( jgsqrtxintw_intrp(:) * ( q_intrp(:) - qexact_intrp(:,ke,iv) )**2 )
366 linf_max_tmp(ke,iv) = maxval(abs(q(:,ke,iv) - qexact(:,ke,iv)))
367
368 numsol_mean_lc(iv) = numsol_mean_lc(iv) + sum( jgsqrtxintw_intrp(:) * q_intrp(:) )
369 exactsol_mean_lc(iv) = exactsol_mean_lc(iv) + sum( jgsqrtxintw_intrp(:) * qexact_intrp(:,ke,iv) )
370 end do
371
372 num_error_linf_lc(iv) = max( num_error_linf_lc(iv), maxval( linf_max_tmp(:,iv) ) )
373 end do
374
375 return
376 end subroutine meshfield_analysis_numerror_base_evaluate_error_lc
377
378 !> Evaluate covariance of numerical and exact solutions at local mesh level
379!OCL SERIAL
380 subroutine meshfield_analysis_numerror_base_evaluate_covariance_lc( base, &
381 cov_numsol_numsol_lc, cov_numsol_exactsol_lc, cov_exactsol_exactsol_lc, &
382 q, qexact, qexact_intrp, numsol_mean, exactsol_mean, &
383 lcmesh, elem )
384
385 implicit none
386 class(meshfieldanalysisnumerrorbase), intent(in) :: base
387 class(localmeshbase), intent(in) :: lcmesh
388 class(elementbase), intent(in) :: elem
389 real(RP), intent(inout) :: cov_numsol_numsol_lc(base%var_num)
390 real(RP), intent(inout) :: cov_numsol_exactsol_lc(base%var_num)
391 real(RP), intent(inout) :: cov_exactsol_exactsol_lc(base%var_num)
392 real(RP), intent(in) :: q(elem%Np,lcmesh%Ne,base%var_num)
393 real(RP), intent(in) :: qexact(elem%Np,lcmesh%Ne,base%var_num)
394 real(RP), intent(in) :: qexact_intrp(base%intrp_np,lcmesh%Ne,base%var_num)
395 real(RP), intent(in) :: numsol_mean(base%var_num)
396 real(RP), intent(in) :: exactsol_mean(base%var_num)
397
398 integer :: iv
399 integer :: ke
400
401 real(RP) :: dq_intrp(base%intrp_np)
402 real(RP) :: JGsqrtxIntw_intrp(base%intrp_np)
403 real(RP) :: dq_exact_intrp(base%intrp_np)
404 !---------------------------------------------------------------------------
405
406 do iv=1, base%var_num
407 !$omp parallel do private(ke, dq_intrp, dq_exact_intrp, JGsqrtxIntw_intrp) reduction(+: cov_numsol_numsol_lc, cov_numsol_exactsol_lc, cov_exactsol_exactsol_lc )
408 do ke=lcmesh%NeS, lcmesh%NeE
409 dq_intrp(:) = matmul( base%IntrpMat, q(:,ke,iv) ) - numsol_mean(iv)
410 dq_exact_intrp(:) = qexact_intrp(:,ke,iv)- exactsol_mean(iv)
411 jgsqrtxintw_intrp(:) = matmul( base%IntrpMat, lcmesh%J(:,ke) * lcmesh%Gsqrt(:,ke) )
412 jgsqrtxintw_intrp(:) = jgsqrtxintw_intrp(:) * base%intw_intrp(:)
413
414 cov_numsol_numsol_lc(iv) = cov_numsol_numsol_lc(iv) + sum( jgsqrtxintw_intrp(:) * dq_intrp(:) * dq_intrp(:) )
415 cov_numsol_exactsol_lc(iv) = cov_numsol_exactsol_lc(iv) + sum( jgsqrtxintw_intrp(:) * dq_intrp(:) * dq_exact_intrp(:) )
416 cov_exactsol_exactsol_lc(iv) = cov_exactsol_exactsol_lc(iv) + sum( jgsqrtxintw_intrp(:) * dq_exact_intrp(:) * dq_exact_intrp(:) )
417 end do
418 end do
419
420 return
421 end subroutine meshfield_analysis_numerror_base_evaluate_covariance_lc
422
423
424!--- private
425
426 !> Get a flag whether to evaluate numerical errors at the current time step
427!OCL SERIAL
428 function numerror_do_step( this, step ) result(do_flag)
429 implicit none
430
431 type(meshfieldanalysisnumerrorbase), intent(inout) :: this
432 integer, intent(in) :: step
433 logical :: do_flag
434 !------------------------------------------------------------------------
435
436 if ( step == 1 .or. time_nstep < step ) then
437 do_flag = .true.
438 return
439 end if
440
441 this%log_rstep = this%log_rstep - 1
442 if ( this%log_rstep == 0 ) then
443 do_flag = .true.
444 this%log_rstep = this%log_step_interval
445 else
446 do_flag = .false.
447 end if
448
449 return
450 end function numerror_do_step
451
module FElib / Element / Base
module FElib / Element / hexahedron
module FElib / Element / line
module FElib / Element / Quadrilateral
module FElib / Mesh / Local, Base
module FElib / Mesh / Base
module FElib / Data / Statistics / numerical error
module FElib / Data / base
Module common / time.
Derived type representing an arbitrary finite element.
Derived type representing a hexahedral element.
Derived type representing a line element.
Derived type representing a quadrilateral element.
Derived type to manage a local computational domain (base type)
Derived type representing a field with local mesh (base type)
Base type to manage a computational mesh.
Derived type representing a field (base type)