SCALE-RM
mod_da_param_estimation.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
9 !-------------------------------------------------------------------------------
10 #include "scalelib.h"
12  !-----------------------------------------------------------------------------
13  !
14  !++ used modules
15  !
16  use scale_precision
17  use scale_io
18  use scale_prof
19 
20  !-----------------------------------------------------------------------------
21  implicit none
22  private
23  !-----------------------------------------------------------------------------
24  !
25  !++ Public procedure
26  !
30 
31  !-----------------------------------------------------------------------------
32  !
33  !++ Public parameters & variables
34  !
35  !-----------------------------------------------------------------------------
36  !
37  !++ Private procedure
38  !
39  private :: estimation_getvar
40  private :: estimation_putvar
41  private :: estimation_log
42  private :: phys2func
43  private :: func2phys
44 
45  !-----------------------------------------------------------------------------
46  !
47  !++ Private parameters & variables
48  !
49  integer, parameter :: MAXNUM_PARAM_ESTIMATION = 100
50 
51  integer :: NUM_PARAM_ESTIMATION
52  logical :: DO_PARAM_ESTIMATION
53 
54  character(len=H_SHORT) :: ESTIMATION_TARGET(MAXNUM_PARAM_ESTIMATION)
55 
56  logical :: PEST_TRANSLATION(MAXNUM_PARAM_ESTIMATION)
57 
58  real(RP) :: PEST_ULIMIT(MAXNUM_PARAM_ESTIMATION)
59  real(RP) :: PEST_LLIMIT(MAXNUM_PARAM_ESTIMATION)
60 
61  real(RP), allocatable :: param_array(:,:)
62 
63  integer :: datatype
64 
65  !-----------------------------------------------------------------------------
66 contains
67  !-----------------------------------------------------------------------------
69  subroutine da_param_estimation_setup
70  use mpi
71  use scale_prc, only: &
72  prc_abort
73  use scale_comm_ensemble, only: &
74  ensemble_nprocs => comm_ensemble_nprocs, &
75  ensemble_myrank => comm_ensemble_myrank
76  implicit none
77 
78  namelist / param_da_param_estimation / &
79  estimation_target, &
80  pest_translation, &
81  pest_ulimit, &
82  pest_llimit
83 
84  integer :: v
85  integer :: ierr
86  !---------------------------------------------------------------------------
87 
88  num_param_estimation = 0
89  do_param_estimation = .false.
90 
91  estimation_target(:) = ''
92 
93  pest_translation(:) = .false.
94 
95  pest_ulimit(:) = huge(0.0_rp)
96  pest_llimit(:) = -huge(0.0_rp)
97 
98  !--- gather parameters from ensemble communication
99  if ( rp == sp ) then
100  datatype = mpi_real
101  else if( rp == dp ) then
102  datatype = mpi_double_precision
103  else
104  log_error("DA_param_estimation_setup",*) 'The precision has not been implemented yet:', rp
105  call prc_abort
106  endif
107 
108  !--- read namelist
109  rewind(io_fid_conf)
110  read(io_fid_conf,nml=param_da_param_estimation,iostat=ierr)
111  if( ierr < 0 ) then !--- missing
112  log_info("DA_param_estimation_setup",*) 'Not found namelist. Default used.'
113  elseif( ierr > 0 ) then !--- fatal error
114  log_error("DA_param_estimation_setup",*) 'Not appropriate names in namelist PARAM_DA_PARAM_ESTIMATION. Check!'
115  call prc_abort
116  endif
117  log_nml(param_da_param_estimation)
118 
119  do v = 1, maxnum_param_estimation
120  if( trim(estimation_target(v)) /= '' ) then
121  num_param_estimation = num_param_estimation + 1
122  end if
123  end do
124 
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, ')'
127  call prc_abort
128  end if
129 
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.
133 
134  allocate( param_array( ensemble_nprocs, num_param_estimation ) )
135 
136  call estimation_getvar
137  call estimation_log
138 
139  end if
140 
141  return
142  end subroutine da_param_estimation_setup
143 
144  !-----------------------------------------------------------------------------
147  implicit none
148  !---------------------------------------------------------------------------
149 
150  if( allocated( param_array ) ) deallocate( param_array )
151 
152  return
153  end subroutine da_param_estimation_finalize
154 
155  !-----------------------------------------------------------------------------
157  subroutine da_param_estimation_update
158  use scale_comm_ensemble, only: &
159  ensemble_nprocs => comm_ensemble_nprocs
160  use scale_letkf, only: &
162  implicit none
163 
164  integer :: n, v
165  !---------------------------------------------------------------------------
166 
167  if( .NOT. do_param_estimation ) return
168 
169  !--- get parameters for estimation
170  call estimation_getvar
171 
172  do v = 1, num_param_estimation
173  do n = 1, ensemble_nprocs
174  if( pest_translation(v) ) then ! encoding function by Kotsuki (2015)
175  param_array(n,v) = phys2func( v, param_array(n,v) )
176  end if
177  end do
178  end do
179 
180  !--- execute parameter estimation
181  call letkf_param_estimation_system( num_param_estimation, &
182  param_array(:,:) )
183 
184  do v = 1, num_param_estimation
185  do n = 1, ensemble_nprocs
186  if( pest_translation(v) ) then ! decoding function by Kotsuki (2015)
187  param_array(n,v) = func2phys( v, param_array(n,v) )
188  end if
189  end do
190  end do
191 
192  !--- overwrite parameters
193  call estimation_putvar
194  call estimation_log
195 
196  return
197  end subroutine da_param_estimation_update
198 
199  subroutine estimation_getvar
200  use mpi
201  use scale_prc, only: &
202  prc_abort
203  use scale_const, only: &
204  undef => const_undef
205  use scale_comm_ensemble, only: &
206  ensemble_world => comm_ensemble_world, &
207  ensemble_nprocs => comm_ensemble_nprocs, &
208  ensemble_myrank => comm_ensemble_myrank
209  use scale_atmos_phy_mp_tomita08, only: &
211  use scale_atmos_phy_cp_kf, only: &
213  implicit none
214 
215  real(rp), allocatable :: send(:)
216  real(rp), allocatable :: recv(:)
217 
218  integer :: n, v
219  integer :: ierr
220  !---------------------------------------------------------------------------
221 
222  do v = 1, num_param_estimation
223  select case( trim(estimation_target(v)) )
224  case('MP_tomita08_drag_g')
225  call atmos_phy_mp_tomita08_getvar( out_drag_g=param_array(1+ensemble_myrank,v) )
226  case('MP_tomita08_re_qc')
227  call atmos_phy_mp_tomita08_getvar( out_re_qc=param_array(1+ensemble_myrank,v) )
228  case('MP_tomita08_re_qi')
229  call atmos_phy_mp_tomita08_getvar( out_re_qi=param_array(1+ensemble_myrank,v) )
230  case('MP_tomita08_Cr')
231  call atmos_phy_mp_tomita08_getvar( out_cr=param_array(1+ensemble_myrank,v) )
232  case('MP_tomita08_Cs')
233  call atmos_phy_mp_tomita08_getvar( out_cs=param_array(1+ensemble_myrank,v) )
234  case('CP_kf_delcape')
235  call atmos_phy_cp_kf_getvar( out_delcape=param_array(1+ensemble_myrank,v) )
236  case('CP_kf_deeplifetime')
237  call atmos_phy_cp_kf_getvar( out_deeplifetime=param_array(1+ensemble_myrank,v) )
238  case('CP_kf_shallowlifetime')
239  call atmos_phy_cp_kf_getvar( out_shallowlifetime=param_array(1+ensemble_myrank,v) )
240  case default
241  log_error("DA_param_estimation_update",*) 'Invalid ESTIMATION_TARGET:', trim(estimation_target(v))
242  call prc_abort
243  end select
244  end do
245 
246  allocate( send(num_param_estimation*ensemble_nprocs) )
247  allocate( recv(num_param_estimation*ensemble_nprocs) )
248 
249  send(:) = undef
250  recv(:) = undef
251 
252  do v = 1, num_param_estimation
253  send( v + ensemble_myrank*num_param_estimation ) = param_array(1+ensemble_myrank,v)
254  end do
255 
256  n = ensemble_myrank * num_param_estimation + 1
257 
258  call mpi_allgather( send(n), &
259  num_param_estimation, &
260  datatype, &
261  recv(1), &
262  num_param_estimation, &
263  datatype, &
264  ensemble_world, &
265  ierr )
266 
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 )
270  end do
271  end do
272 
273  deallocate( send )
274  deallocate( recv )
275 
276  return
277  end subroutine estimation_getvar
278 
279  subroutine estimation_putvar
280  use scale_prc, only: &
281  prc_abort
282  use scale_comm_ensemble, only: &
283  ensemble_myrank => comm_ensemble_myrank
284  use scale_atmos_phy_mp_tomita08, only: &
286  use scale_atmos_phy_cp_kf, only: &
288  implicit none
289 
290  integer :: v
291  !---------------------------------------------------------------------------
292 
293  do v = 1, num_param_estimation
294  select case( trim(estimation_target(v)) )
295  case('MP_tomita08_drag_g')
296  call atmos_phy_mp_tomita08_putvar( in_drag_g=param_array(1+ensemble_myrank,v) )
297  case('MP_tomita08_re_qc')
298  call atmos_phy_mp_tomita08_putvar( in_re_qc=param_array(1+ensemble_myrank,v) )
299  case('MP_tomita08_re_qi')
300  call atmos_phy_mp_tomita08_putvar( in_re_qi=param_array(1+ensemble_myrank,v) )
301  case('MP_tomita08_Cr')
302  call atmos_phy_mp_tomita08_putvar( in_cr=param_array(1+ensemble_myrank,v) )
303  case('MP_tomita08_Cs')
304  call atmos_phy_mp_tomita08_putvar( in_cs=param_array(1+ensemble_myrank,v) )
305  case('CP_kf_delcape')
306  call atmos_phy_cp_kf_putvar( in_delcape=param_array(1+ensemble_myrank,v) )
307  case('CP_kf_deeplifetime')
308  call atmos_phy_cp_kf_putvar( in_deeplifetime=param_array(1+ensemble_myrank,v) )
309  case('CP_kf_shallowlifetime')
310  call atmos_phy_cp_kf_putvar( in_shallowlifetime=param_array(1+ensemble_myrank,v) )
311  case default
312  log_error("DA_param_estimation_update",*) 'Invalid ESTIMATION_TARGET:', trim(estimation_target(v))
313  call prc_abort
314  end select
315  end do
316 
317  return
318  end subroutine estimation_putvar
319 
320  subroutine estimation_log
321  use scale_const, only: &
322  undef => const_undef
323  use scale_comm_ensemble, only: &
324  ensemble_nprocs => comm_ensemble_nprocs, &
325  ensemble_myrank => comm_ensemble_myrank
326  use scale_time, only: &
328  use scale_statistics, only: &
329  average => statistics_average, &
330  stddev => statistics_stddev
331  implicit none
332 
333  character(len=20) :: nowdate
334 
335  integer :: i, v
336  !---------------------------------------------------------------------------
337 
338  do v = 1, num_param_estimation
339  nowdate = '****/**/**-**:**:** '
340  write( nowdate( 1: 4), '(i4)' ) time_nowdate(1)
341  write( nowdate( 6: 7), '(i2)' ) time_nowdate(2)
342  write( nowdate( 9:10), '(i2)' ) time_nowdate(3)
343  write( nowdate(12:13), '(i2)' ) time_nowdate(4)
344  write( nowdate(15:16), '(i2)' ) time_nowdate(5)
345  write( nowdate(18:19), '(i2)' ) time_nowdate(6)
346  do i = 1, 19
347  if( nowdate(i:i) == ' ' ) nowdate(i:i) = '0'
348  end do
349 
350  log_info("DA_param_estimation_update",*) 'result [time, name, rank-var, mean, std]: ', &
351  nowdate, &
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 )
356  end do
357 
358  return
359  end subroutine estimation_log
360 
361  !---------------------------------------------------------------------
362  ! Based on the NICAM-LETKF parameter estimation code
363  ! created by by Shunji Kotsuki, RIKEN AICS (Dec 2015)
364  !---------------------------------------------------------------------
365  function phys2func(pidx,phys) ! phys --> func
366  implicit none
367 
368  real(rp) :: phys2func
369 
370  integer, intent(in) :: pidx
371  real(rp), intent(in) :: phys
372 
373  real(rp) :: pmax, pmin, pmean
374  real(rp) :: tmp_phys
375 
376  pmax = pest_ulimit(pidx)
377  pmin = pest_llimit(pidx)
378 
379  pmean = 0.5_rp * (pmax + pmin)
380  tmp_phys = (phys - pmean) / (pmax - pmean)
381 
382  phys2func = 0.5_rp * log( (1.0_rp + tmp_phys) / (1.0_rp - tmp_phys) )
383  !phys2func = tanh((phys - pmean) / (pmax - pmean))
384 
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
387  endif
388 
389  return
390  end function phys2func
391 
392  function func2phys(pidx,func) ! func --> phys
393  implicit none
394 
395  real(rp) :: func2phys
396 
397  integer, intent(in) :: pidx
398  real(rp), intent(in) :: func
399 
400  real(rp) :: pmax, pmin, pmean
401 
402  pmax = pest_ulimit(pidx)
403  pmin = pest_llimit(pidx)
404 
405  pmean = 0.5_rp * (pmax + pmin)
406 
407  func2phys = tanh(func) * (pmax - pmean) + pmean
408  !func2phys = 0.5_RP * log( (1.0_RP + func) / (1.0_RP - func) ) * (pmax - pmean) + pmean
409 
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
412  endif
413 
414  return
415  end function func2phys
416 
417 end module mod_da_param_estimation
scale_statistics
module Statistics
Definition: scale_statistics.F90:11
scale_precision::sp
integer, parameter, public sp
Definition: scale_precision.F90:31
scale_atmos_phy_mp_tomita08::atmos_phy_mp_tomita08_putvar
subroutine, public atmos_phy_mp_tomita08_putvar(in_drag_g, in_re_qc, in_re_qi, in_Cr, in_Cs)
overwrite private variables
Definition: scale_atmos_phy_mp_tomita08.F90:671
scale_comm_ensemble::comm_ensemble_world
integer, public comm_ensemble_world
Definition: scale_comm_ensemble.F90:35
scale_prc::prc_abort
subroutine, public prc_abort
Abort Process.
Definition: scale_prc.F90:350
mod_da_param_estimation
module Parameter Estimation
Definition: mod_da_param_estimation.F90:11
scale_atmos_phy_mp_tomita08
module atmosphere / physics / microphysics / Tomita08
Definition: scale_atmos_phy_mp_tomita08.F90:13
scale_comm_ensemble
module Communication for Ensemble system
Definition: scale_comm_ensemble.F90:12
scale_precision
module PRECISION
Definition: scale_precision.F90:14
scale_letkf
module LETKF for Data-Assimilation
Definition: scale_letkf.F90:12
scale_atmos_phy_mp_tomita08::atmos_phy_mp_tomita08_getvar
subroutine, public atmos_phy_mp_tomita08_getvar(out_drag_g, out_re_qc, out_re_qi, out_Cr, out_Cs)
read private variables
Definition: scale_atmos_phy_mp_tomita08.F90:703
scale_atmos_phy_cp_kf
module atmosphere / physics / cumulus / Kain-Fritsch
Definition: scale_atmos_phy_cp_kf.F90:45
mod_da_param_estimation::da_param_estimation_finalize
subroutine, public da_param_estimation_finalize
finalize
Definition: mod_da_param_estimation.F90:147
scale_atmos_phy_cp_kf::atmos_phy_cp_kf_putvar
subroutine, public atmos_phy_cp_kf_putvar(in_delcape, in_deeplifetime, in_shallowlifetime)
overwrite private variables
Definition: scale_atmos_phy_cp_kf.F90:453
scale_prc
module PROCESS
Definition: scale_prc.F90:11
scale_io
module STDIO
Definition: scale_io.F90:10
mod_da_param_estimation::da_param_estimation_update
subroutine, public da_param_estimation_update
Data Assimilation.
Definition: mod_da_param_estimation.F90:158
scale_comm_ensemble::comm_ensemble_nprocs
integer, public comm_ensemble_nprocs
Definition: scale_comm_ensemble.F90:37
scale_const
module CONSTANT
Definition: scale_const.F90:11
scale_letkf::letkf_param_estimation_system
subroutine, public letkf_param_estimation_system(PEST_PMAX, PEST_VAR0)
Definition: scale_letkf.F90:2873
scale_prof
module profiler
Definition: scale_prof.F90:11
scale_precision::dp
integer, parameter, public dp
Definition: scale_precision.F90:32
scale_time
module TIME
Definition: scale_time.F90:11
scale_time::time_nowdate
integer, dimension(6), public time_nowdate
current time [YYYY MM DD HH MM SS]
Definition: scale_time.F90:68
scale_comm_ensemble::comm_ensemble_myrank
integer, public comm_ensemble_myrank
Definition: scale_comm_ensemble.F90:36
scale_const::const_undef
real(rp), public const_undef
Definition: scale_const.F90:43
scale_io::io_fid_conf
integer, public io_fid_conf
Config file ID.
Definition: scale_io.F90:57
scale_atmos_phy_cp_kf::atmos_phy_cp_kf_getvar
subroutine, public atmos_phy_cp_kf_getvar(out_delcape, out_deeplifetime, out_shallowlifetime)
read private variables
Definition: scale_atmos_phy_cp_kf.F90:473
mod_da_param_estimation::da_param_estimation_setup
subroutine, public da_param_estimation_setup
Setup.
Definition: mod_da_param_estimation.F90:70