39 private :: estimation_getvar
40 private :: estimation_putvar
41 private :: estimation_log
49 integer,
parameter :: MAXNUM_PARAM_ESTIMATION = 100
51 integer :: NUM_PARAM_ESTIMATION
52 logical :: DO_PARAM_ESTIMATION
54 character(len=H_SHORT) :: ESTIMATION_TARGET(MAXNUM_PARAM_ESTIMATION)
56 logical :: PEST_TRANSLATION(MAXNUM_PARAM_ESTIMATION)
58 real(RP) :: PEST_ULIMIT(MAXNUM_PARAM_ESTIMATION)
59 real(RP) :: PEST_LLIMIT(MAXNUM_PARAM_ESTIMATION)
61 real(RP),
allocatable :: param_array(:,:)
78 namelist / param_da_param_estimation / &
88 num_param_estimation = 0
89 do_param_estimation = .false.
91 estimation_target(:) =
''
93 pest_translation(:) = .false.
95 pest_ulimit(:) = huge(0.0_rp)
96 pest_llimit(:) = -huge(0.0_rp)
101 else if( rp ==
dp )
then
102 datatype = mpi_double_precision
104 log_error(
"DA_param_estimation_setup",*)
'The precision has not been implemented yet:', rp
110 read(
io_fid_conf,nml=param_da_param_estimation,iostat=ierr)
112 log_info(
"DA_param_estimation_setup",*)
'Not found namelist. Default used.'
113 elseif( ierr > 0 )
then
114 log_error(
"DA_param_estimation_setup",*)
'Not appropriate names in namelist PARAM_DA_PARAM_ESTIMATION. Check!'
117 log_nml(param_da_param_estimation)
119 do v = 1, maxnum_param_estimation
120 if( trim(estimation_target(v)) /=
'' )
then
121 num_param_estimation = num_param_estimation + 1
125 if( num_param_estimation > maxnum_param_estimation )
then
126 log_error(
"DA_param_estimation_setup",*)
'NUM_PARAM_ESTIMATION has exceeded the limit! ( MAX = ', maxnum_param_estimation,
')'
130 if( num_param_estimation > 0 )
then
131 log_info(
"DA_param_estimation_setup",*)
'Set up Parameter Estimation module. The number of estimation target:', num_param_estimation
132 do_param_estimation = .true.
134 allocate( param_array( ensemble_nprocs, num_param_estimation ) )
136 call estimation_getvar
150 if(
allocated( param_array ) )
deallocate( param_array )
167 if( .NOT. do_param_estimation )
return
170 call estimation_getvar
172 do v = 1, num_param_estimation
173 do n = 1, ensemble_nprocs
174 if( pest_translation(v) )
then
175 param_array(n,v) = phys2func( v, param_array(n,v) )
184 do v = 1, num_param_estimation
185 do n = 1, ensemble_nprocs
186 if( pest_translation(v) )
then
187 param_array(n,v) = func2phys( v, param_array(n,v) )
193 call estimation_putvar
199 subroutine estimation_getvar
215 real(rp),
allocatable :: send(:)
216 real(rp),
allocatable :: recv(:)
222 do v = 1, num_param_estimation
223 select case( trim(estimation_target(v)) )
224 case(
'MP_tomita08_drag_g')
226 case(
'MP_tomita08_re_qc')
228 case(
'MP_tomita08_re_qi')
230 case(
'MP_tomita08_Cr')
232 case(
'MP_tomita08_Cs')
234 case(
'CP_kf_delcape')
236 case(
'CP_kf_deeplifetime')
238 case(
'CP_kf_shallowlifetime')
241 log_error(
"DA_param_estimation_update",*)
'Invalid ESTIMATION_TARGET:', trim(estimation_target(v))
246 allocate( send(num_param_estimation*ensemble_nprocs) )
247 allocate( recv(num_param_estimation*ensemble_nprocs) )
252 do v = 1, num_param_estimation
253 send( v + ensemble_myrank*num_param_estimation ) = param_array(1+ensemble_myrank,v)
256 n = ensemble_myrank * num_param_estimation + 1
258 call mpi_allgather( send(n), &
259 num_param_estimation, &
262 num_param_estimation, &
267 do v = 1, num_param_estimation
268 do n = 1, ensemble_nprocs
269 param_array(n,v) = recv( v + (n-1)*num_param_estimation )
277 end subroutine estimation_getvar
279 subroutine estimation_putvar
293 do v = 1, num_param_estimation
294 select case( trim(estimation_target(v)) )
295 case(
'MP_tomita08_drag_g')
297 case(
'MP_tomita08_re_qc')
299 case(
'MP_tomita08_re_qi')
301 case(
'MP_tomita08_Cr')
303 case(
'MP_tomita08_Cs')
305 case(
'CP_kf_delcape')
307 case(
'CP_kf_deeplifetime')
309 case(
'CP_kf_shallowlifetime')
312 log_error(
"DA_param_estimation_update",*)
'Invalid ESTIMATION_TARGET:', trim(estimation_target(v))
318 end subroutine estimation_putvar
320 subroutine estimation_log
329 average => statistics_average, &
330 stddev => statistics_stddev
333 character(len=20) :: nowdate
338 do v = 1, num_param_estimation
339 nowdate =
'****/**/**-**:**:** '
347 if( nowdate(i:i) ==
' ' ) nowdate(i:i) =
'0'
350 log_info(
"DA_param_estimation_update",*)
'result [time, name, rank-var, mean, std]: ', &
352 trim(estimation_target(v)), &
353 param_array(1+ensemble_myrank,v), &
354 average( ensemble_nprocs, param_array(:,v), undef ), &
355 stddev( ensemble_nprocs, param_array(:,v), undef )
359 end subroutine estimation_log
365 function phys2func(pidx,phys)
368 real(rp) :: phys2func
370 integer,
intent(in) :: pidx
371 real(rp),
intent(in) :: phys
373 real(rp) :: pmax, pmin, pmean
376 pmax = pest_ulimit(pidx)
377 pmin = pest_llimit(pidx)
379 pmean = 0.5_rp * (pmax + pmin)
380 tmp_phys = (phys - pmean) / (pmax - pmean)
382 phys2func = 0.5_rp * log( (1.0_rp + tmp_phys) / (1.0_rp - tmp_phys) )
385 if (phys <= pmin .or. pmax <= phys)
then
386 log_info(
'DA_param_estimation (phys2func)',*)
'Waring: Estimated parameter value is outside of the limit! (pmin/pmax/phys)', pmin, pmax, phys
390 end function phys2func
392 function func2phys(pidx,func)
395 real(rp) :: func2phys
397 integer,
intent(in) :: pidx
398 real(rp),
intent(in) :: func
400 real(rp) :: pmax, pmin, pmean
402 pmax = pest_ulimit(pidx)
403 pmin = pest_llimit(pidx)
405 pmean = 0.5_rp * (pmax + pmin)
407 func2phys = tanh(func) * (pmax - pmean) + pmean
410 if (func2phys <= pmin .or. pmax <= func2phys)
then
411 log_info(
'DA_param_estimation (func2phys)',*)
'Waring: Estimated parameter value is outside of the limit! (pmin/pmax/phys)', pmin, pmax, func2phys
415 end function func2phys