LCOV - code coverage report
Current view: top level - src - mo_likelihood.f90 (source / functions) Hit Total Coverage
Test: forces coverage Lines: 37 56 66.1 %
Date: 2024-03-13 19:03:28 Functions: 5 7 71.4 %

          Line data    Source code
       1             : !> \file mo_likelihood.f90
       2             : !> \brief \copybrief mo_likelihood
       3             : !> \details \copydetails mo_likelihood
       4             : 
       5             : !>  \brief Added for testing purposes of test_mo_mcmc
       6             : !> \copyright Copyright 2005-\today, the CHS Developers, Sabine Attinger: All rights reserved.
       7             : !! FORCES is released under the LGPLv3+ license \license_note
       8             : module mo_likelihood
       9             : 
      10             :   USE mo_kind,   only: i4, dp
      11             :   USE mo_moment, only: stddev
      12             :   use mo_optimization_utils, only: eval_interface
      13             : 
      14             :   Implicit NONE
      15             : 
      16             :   PRIVATE
      17             : 
      18             :   PUBLIC :: data
      19             :   PUBLIC :: model_dp
      20             :   PUBLIC :: likelihood_dp,        loglikelihood_dp        ! "real" likelihood  (sigma is an error model or given)
      21             :   PUBLIC :: likelihood_stddev_dp, loglikelihood_stddev_dp ! "faked" likelihood (sigma is computed by obs vs model)
      22             :   PUBLIC :: setmeas
      23             : 
      24             :   ! -------------------------------
      25             :   !> \brief synthetic data
      26             :   !> \details Data generated with
      27             :   !!     paraset(1) = 1.0
      28             :   !!     paraset(2) = 2.0
      29             :   !!     paraset(3) = 3.0
      30             :   !! plus additive, Gaussian distributed error with mu=0.0 and sigma=0.5
      31             :   INTERFACE data
      32             :      MODULE PROCEDURE data_dp
      33             :   END INTERFACE data
      34             : 
      35             :   !> \brief set meas
      36             :   INTERFACE setmeas
      37             :      MODULE PROCEDURE setmeas_dp
      38             :   END INTERFACE setmeas
      39             : 
      40             :   REAL(DP),DIMENSION(100,2)  :: meas                   ! measurements
      41             :   REAL(DP),PARAMETER         :: stddev_global=0.5_dp   ! standard deviation of measurement error
      42             : 
      43             :   ! ------------------------------------------------------------------
      44             : 
      45             : CONTAINS
      46             : 
      47             :   ! -------------------------------
      48             :   !> \brief A Likelihood function: "real" likelihood  (sigma is an error model or given)
      49           0 :   function likelihood_dp(paraset, eval, stddev_in, stddev_new, likeli_new)
      50             :     REAL(DP), DIMENSION(:), INTENT(IN)            :: paraset          ! parameter set
      51             :     procedure(eval_interface), INTENT(IN), pointer :: eval
      52             :     REAL(DP),               INTENT(IN), optional  :: stddev_in        ! standard deviation of data
      53             :     REAL(DP),               INTENT(OUT), OPTIONAL :: stddev_new       ! standard deviation of errors using paraset
      54             :     REAL(DP),               INTENT(OUT), OPTIONAL :: likeli_new       ! likelihood using stddev_new,
      55             :     !                                                                 ! i.e. using new parameter set
      56             :     REAL(DP)                                      :: likelihood_dp
      57             : 
      58             :     ! local
      59           0 :     REAL(DP), DIMENSION(size(meas,1))   :: errors
      60           0 :     real(dp), dimension(:,:), allocatable :: runoff
      61             : 
      62           0 :     call eval(paraset, runoff=runoff)
      63           0 :     errors(:) = runoff(:,1)-data()
      64           0 :     likelihood_dp = exp(-0.5_dp * sum( errors(:) * errors(:) / stddev_global**2 ))
      65             : 
      66           0 :   end function likelihood_dp
      67             : 
      68             :   ! -------------------------------
      69             :   !> \brief A Log-Likelihood function: "real" likelihood  (sigma is an error model or given)
      70       86763 :   function loglikelihood_dp(paraset, eval, stddev_in, stddev_new, likeli_new)
      71             :     REAL(DP), DIMENSION(:), INTENT(IN)            :: paraset          ! parameter set
      72             :     procedure(eval_interface), INTENT(IN), pointer :: eval
      73             :     REAL(DP),               INTENT(IN), optional  :: stddev_in        ! standard deviation of data
      74             :     REAL(DP),               INTENT(OUT), OPTIONAL :: stddev_new       ! standard deviation of errors using paraset
      75             :     REAL(DP),               INTENT(OUT), OPTIONAL :: likeli_new       ! likelihood using stddev_new,
      76             :     !                                                                 ! i.e. using new parameter set
      77             :     REAL(DP)                                      :: loglikelihood_dp
      78             : 
      79             :     ! local
      80     8763063 :     REAL(DP), DIMENSION(size(meas,1))   :: errors
      81       86763 :     real(dp), dimension(:,:), allocatable :: runoff
      82             : 
      83       86763 :     call eval(paraset, runoff=runoff)
      84     8763063 :     errors(:) = runoff(:,1)-data()
      85     8763063 :     loglikelihood_dp = -0.5_dp * sum( errors(:) * errors(:) / stddev_global**2 )
      86             : 
      87       86763 :   end function loglikelihood_dp
      88             : 
      89             :   ! -------------------------------
      90             :   !> \brief A Likelihood function: "faked" likelihood (sigma is computed by obs vs model)
      91           0 :   function likelihood_stddev_dp(paraset, eval, stddev_in, stddev_new, likeli_new)
      92             :     REAL(DP), DIMENSION(:), INTENT(IN)            :: paraset          ! parameter set
      93             :     procedure(eval_interface), INTENT(IN), pointer :: eval
      94             :     REAL(DP),               INTENT(IN), optional  :: stddev_in        ! standard deviation of data
      95             :     REAL(DP),               INTENT(OUT), OPTIONAL :: stddev_new       ! standard deviation of errors using paraset
      96             :     REAL(DP),               INTENT(OUT), OPTIONAL :: likeli_new       ! likelihood using stddev_new,
      97             :     !                                                                 ! i.e. using new parameter set
      98             :     REAL(DP)                                      :: likelihood_stddev_dp
      99             : 
     100             :     ! local
     101           0 :     REAL(DP), DIMENSION(size(meas,1))   :: errors
     102           0 :     REAL(DP)                            :: stddev_err
     103           0 :     real(dp), dimension(:,:), allocatable :: runoff
     104             : 
     105           0 :     call eval(paraset, runoff=runoff)
     106           0 :     errors(:) = runoff(:,1)-data()
     107           0 :     likelihood_stddev_dp = exp(-0.5_dp * sum( errors(:) * errors(:) / stddev_in**2 ))
     108             : 
     109             :     ! optional out
     110           0 :     stddev_err = stddev(errors)
     111           0 :     if (present( stddev_new )) then
     112           0 :        stddev_new = stddev_err
     113             :     end if
     114           0 :     if (present( likeli_new )) then
     115           0 :        likeli_new = exp(-0.5_dp * sum( errors(:) * errors(:) / stddev_err**2 ))
     116             :     end if
     117             : 
     118       86763 :   end function likelihood_stddev_dp
     119             : 
     120             :   ! -------------------------------
     121             :   !> \brief A Log-Likelihood_stddev function: "faked" likelihood (sigma is computed by obs vs model)
     122      182156 :   function loglikelihood_stddev_dp(paraset, eval, stddev_in, stddev_new, likeli_new)
     123             :     REAL(DP), DIMENSION(:), INTENT(IN)            :: paraset          ! parameter set
     124             :     procedure(eval_interface), INTENT(IN), pointer :: eval
     125             :     REAL(DP),               INTENT(IN), optional  :: stddev_in        ! standard deviation of data
     126             :     REAL(DP),               INTENT(OUT), OPTIONAL :: stddev_new       ! standard deviation of errors using paraset
     127             :     REAL(DP),               INTENT(OUT), OPTIONAL :: likeli_new       ! likelihood using stddev_new,
     128             :     !                                                                 ! i.e. using new parameter set
     129             :     REAL(DP)                                      :: loglikelihood_stddev_dp
     130             : 
     131             :     ! local
     132    18397756 :     REAL(DP), DIMENSION(size(meas,1))   :: errors
     133      182156 :     REAL(DP)                            :: stddev_err
     134      182156 :     real(dp), dimension(:,:), allocatable :: runoff
     135             : 
     136      182156 :     call eval(paraset, runoff=runoff)
     137    18397756 :     errors(:) = runoff(:,1)-data()
     138    18397756 :     loglikelihood_stddev_dp = -0.5_dp * sum( errors(:) * errors(:) / stddev_in**2 )
     139             : 
     140             :     ! optional out
     141      182156 :     stddev_err = stddev(errors)
     142      182156 :     if (present( stddev_new )) then
     143       39002 :        stddev_new = stddev_err
     144             :     end if
     145      182156 :     if (present( likeli_new )) then
     146     3939202 :        likeli_new = -0.5_dp * sum( errors(:) * errors(:) / stddev_err**2 )
     147             :     end if
     148             : 
     149      182156 :   end function loglikelihood_stddev_dp
     150             : 
     151             :   ! -------------------------------
     152             :   !> \brief A Model: p1*x^2 + p2*x + p3
     153      268919 :   subroutine model_dp(parameterset, opti_domain_indices, runoff, smOptiSim, neutronsOptiSim, etOptiSim, twsOptiSim, &
     154             :     lake_level, lake_volume, lake_area, lake_spill, lake_outflow, BFI)
     155             : 
     156      182156 :     use mo_kind, only: dp
     157             :     use mo_optimization_types, only: optidata_sim
     158             :     !! !$ USE omp_lib,    only: OMP_GET_THREAD_NUM
     159             : 
     160             :     real(dp),    dimension(:), intent(in) :: parameterset
     161             :     integer(i4), dimension(:),                 optional, intent(in)  :: opti_domain_indices
     162             :     real(dp),    dimension(:, :), allocatable, optional, intent(out) :: runoff        ! dim1=time dim2=gauge
     163             :     type(optidata_sim), dimension(:), optional, intent(inout) :: smOptiSim       ! dim1=ncells, dim2=time
     164             :     type(optidata_sim), dimension(:), optional, intent(inout) :: neutronsOptiSim ! dim1=ncells, dim2=time
     165             :     type(optidata_sim), dimension(:), optional, intent(inout) :: etOptiSim       ! dim1=ncells, dim2=time
     166             :     type(optidata_sim), dimension(:), optional, intent(inout) :: twsOptiSim      ! dim1=ncells, dim2=time
     167             :     real(dp), dimension(:, :), allocatable, optional, intent(out) :: lake_level    !< dim1=time dim2=lake
     168             :     real(dp), dimension(:, :), allocatable, optional, intent(out) :: lake_volume   !< dim1=time dim2=lake
     169             :     real(dp), dimension(:, :), allocatable, optional, intent(out) :: lake_area     !< dim1=time dim2=lake
     170             :     real(dp), dimension(:, :), allocatable, optional, intent(out) :: lake_spill    !< dim1=time dim2=lake
     171             :     real(dp), dimension(:, :), allocatable, optional, intent(out) :: lake_outflow  !< dim1=time dim2=lake
     172             :     real(dp),    dimension(:), allocatable, optional, intent(out) :: BFI         !< baseflow index, dim1=domainID
     173             :     integer(i4) :: i, n
     174             :     ! for OMP
     175             :     !! !$  integer(i4)                           :: n_threads, is_thread
     176             : 
     177      268919 :     n = size(meas,1)
     178      268919 :     allocate(runoff(n, 1))
     179             : 
     180             :     !! !$ is_thread = OMP_GET_THREAD_NUM()
     181             :     !! !$ write(*,*) 'OMP_thread: ', is_thread
     182             : 
     183             :     !$OMP parallel default(shared) &
     184             :     !$OMP private(i)
     185             :     !$OMP do
     186    27160819 :     do i=1, n
     187             :        !! !$ if (is_thread /= 0) write(*,*) '    OMP_thread-1: ', is_thread
     188    27160819 :        runoff(i,1) = parameterset(1) * meas(i,1) * meas(i,1) + parameterset(2) * meas(i,1) + parameterset(3)
     189             :     end do
     190             :     !$OMP end do
     191             :     !$OMP end parallel
     192             : 
     193      268919 :   end subroutine model_dp
     194             : 
     195      537838 :   function data_dp()
     196      268919 :     use mo_kind
     197             :     REAL(DP), DIMENSION(size(meas,1))      :: data_dp
     198             : 
     199    27160819 :     data_dp = meas(:,2)
     200             : 
     201      268919 :   end function data_dp
     202             : 
     203           1 :   subroutine setmeas_dp()
     204             : 
     205             :     integer(i4) :: i
     206             : 
     207         101 :     do i=1,100
     208         101 :        meas(i,1) = real(i,dp)
     209             :     end do
     210             : 
     211             :     meas(:,2) = (/ 5.49537_dp, 10.7835_dp, 17.6394_dp, 26.8661_dp, 36.9247_dp, 50.9517_dp, 66.2058_dp, &
     212             :          82.9703_dp, 101.26_dp, 123.076_dp, 145.457_dp, 171.078_dp, 198.349_dp, 227.23_dp, 257.922_dp, &
     213             :          290.098_dp, 325.775_dp, 362.724_dp, 402.669_dp, 442.461_dp, 486.122_dp, 531.193_dp, &
     214             :          577.931_dp, 627.091_dp, 678.096_dp, 731.364_dp, 786.039_dp, 843.531_dp, 903.126_dp, &
     215             :          963.037_dp, 1025.85_dp, 1091.85_dp, 1158.47_dp, 1226.65_dp, 1298.25_dp, 1370.87_dp, &
     216             :          1444.96_dp, 1522.6_dp, 1602.6_dp, 1684.38_dp, 1765.15_dp, 1850.74_dp, 1937.85_dp, 2027.41_dp, &
     217             :          2118.44_dp, 2210.62_dp, 2306.9_dp, 2403.27_dp, 2501.83_dp, 2602.96_dp, 2705.29_dp, &
     218             :          2811.44_dp, 2917.82_dp, 3027.09_dp, 3137.64_dp, 3250.86_dp, 3366.67_dp, 3482.56_dp, &
     219             :          3602.37_dp, 3722.55_dp, 3845.8_dp, 3970.15_dp, 4098.15_dp, 4227.27_dp, 4357.77_dp, &
     220             :          4491.49_dp, 4626.23_dp, 4762.95_dp, 4901.15_dp, 5042.95_dp, 5184.86_dp, 5330.4_dp, &
     221             :          5478.11_dp, 5626.97_dp, 5776.94_dp, 5931.15_dp, 6085.9_dp, 6242.7_dp, 6402.17_dp, 6563.46_dp, &
     222             :          6726.37_dp, 6890.34_dp, 7058.4_dp, 7227.17_dp, 7397.09_dp, 7570.77_dp, 7745.95_dp, &
     223             :          7923.72_dp, 8102.21_dp, 8282.98_dp, 8465.42_dp, 8651.37_dp, 8838.43_dp, 9027.57_dp, &
     224         101 :          9219.21_dp, 9411.24_dp, 9606.31_dp, 9802.88_dp, 10002.3_dp, 10202.6_dp /)
     225      268919 :   end subroutine setmeas_dp
     226             : 
     227             : end module mo_likelihood

Generated by: LCOV version 1.16