module mod_monte use fgsl use, intrinsic :: iso_c_binding implicit none real(fgsl_double), parameter :: exact = 1.3932039296856768_fgsl_double integer(fgsl_size_t), parameter :: calls = 500000 contains function g(v_c, n, params) bind(c) integer(c_size_t), value :: n type(c_ptr), value :: v_c, params real(c_double) :: g real(c_double), dimension(:), pointer :: v call c_f_pointer(v_c, v, [n]) g = 1.0_c_double/(m_pi**3)/ & (1.0_fgsl_double - cos(v(1))*cos(v(2))*cos(v(3))) end function g subroutine display_results(title,result,error) character(kind=fgsl_char,len=*), intent(in) :: title real(fgsl_double), intent(in) :: result, error write(6, '(A,'' ================='')') trim(title) write(6, '(''result = '',F10.6)') result write(6, '(''sigma = '',F10.6)') error write(6, '(''exact = '',F10.6)') exact write(6, '(''error = '',F10.6,'' = '',F5.1,'' sigma'')') & result - exact, abs(result - exact) / error end subroutine display_results end module mod_monte program monte ! Computation of the integral, ! ! I = int (dx dy dz)/(2pi)^3 1/(1-cos(x)cos(y)cos(z)) ! ! over (-pi,-pi,-pi) to (+pi, +pi, +pi). The exact answer ! is Gamma(1/4)^4/(4 pi^3). This example is taken from ! C.Itzykson, J.M.Drouffe, "Statistical Field Theory - ! Volume 1", Section 1.1, p21, which cites the original ! paper M.L.Glasser, I.J.Zucker, Proc.Natl.Acad.Sci.USA 74 ! 1800 (1977) ! For simplicity we compute the integral over the region ! (0,0,0) -> (pi,pi,pi) and multiply by 8 use mod_monte implicit none real(fgsl_double) :: chisq, xl(3), xu(3), res, err, y, yy, yyy integer(fgsl_int) :: status, stage, mode, verbose integer(fgsl_size_t) :: its type(fgsl_file) :: file type(fgsl_rng) :: r type(fgsl_rng_type) :: t type(fgsl_monte_plain_state) :: s type(fgsl_monte_miser_state) :: m type(fgsl_monte_vegas_state) :: v type(fgsl_monte_function) :: gfun type(c_ptr) :: ptr ! xl = 0.0_fgsl_double ; xu = m_pi t = fgsl_rng_env_setup() r = fgsl_rng_alloc(t) gfun = fgsl_monte_function_init(g, 3_fgsl_size_t, ptr) s = fgsl_monte_plain_alloc(3_fgsl_size_t) status = fgsl_monte_plain_integrate(gfun, xl, xu, 3_fgsl_size_t, & calls, r, s, res, err) call fgsl_monte_plain_free(s) call display_results('plain',res,err) ! m = fgsl_monte_miser_alloc(3_fgsl_size_t) status = fgsl_monte_miser_integrate(gfun, xl, xu, 3_fgsl_size_t, & calls, r, m, res, err) call fgsl_monte_miser_free(m) call display_results('miser',res,err) ! v = fgsl_monte_vegas_alloc(3_fgsl_size_t) status = fgsl_monte_vegas_integrate(gfun, xl, xu, 3_fgsl_size_t, & 10000_fgsl_size_t, r, v, res, err) call display_results('vegas warm-up',res,err) write(6, *) 'converging ...' do status = fgsl_monte_vegas_integrate(gfun, xl, xu, 3_fgsl_size_t, & calls/5_fgsl_size_t, r, v, res, err) call fgsl_monte_vegas_getparams(v, y, yy, chisq, yyy, & its, stage, mode, verbose, file) write(6, '(''result = '',F10.6,'' sigma = '',F10.6, & & '' chisq/dof = '',F6.1)') res,err,chisq if (abs(chisq - 1.0_fgsl_double) <= 0.5_fgsl_double) exit end do call display_results('vegas converged',res,err) call fgsl_monte_vegas_free(v) call fgsl_monte_function_free(gfun) call fgsl_rng_free(r) end program monte