!****************************************************************************
!
!	MODULE:  Params
!
!	PURPOSE:  Declares and initializes global variables
!			 
!	AUTHOR:	 Ben Malin 
!
!	DATE:  11/2007
!****************************************************************************

module Params
  
  implicit none
  
  integer,parameter :: prec = selected_real_kind(15,307)
  real(prec),parameter :: pie = 3.1415926535897932
  
  !------------------------------
  !Number of 'state' variables
  !------------------------------
  integer,parameter :: N = COUNTRIES 	   !Number of countries  
  integer,parameter :: d = 2*COUNTRIES !2*N!   !Dimension of state space (capital and tech shock)
  integer,parameter :: q = 2*COUNTRIES+2 !d+2!   !In smolyak interpolation algorithm, lambda = q-d

  !----------------------
  !Parameters of model
  !----------------------
  real(prec),parameter :: gamma = 1.0	! Risk aversion parameter
  real(prec),parameter :: betah = 0.99	! Subjective discount factor
  real(prec),parameter :: alpha = 0.36	! Capital Share
  real(prec),parameter :: delta = 0.025	! Depreciation
  real(prec) :: kappa = 0.5		! Adjustment Cost parameter  ("phi" in paper)

  real(prec) :: A_tfp = (1-betah)/(alpha*betah)	 !Total Factor Productivity
  real(prec),parameter :: sigma = 0.01   !var of tech. shock
  real(prec),parameter :: rho = 0.95     !persistence of tech. shock
  
  real(prec),dimension(N) :: Pareto    !Pareto weight for each country  

  !--------------------------------
  !Variables for grid subroutine
  !--------------------------------
  real(prec) :: kss	! deterministic steady state capital stock
  real(prec) :: kmax	! used to put upper bound on capital grid
  real(prec) :: kmin	! used to put lower bound on capital grid

  real(prec) :: zmax	! largest positive shock is e^(zmax)
  real(prec) :: zmin	! largest negative shock is e^(zmin)
  
  !--------------------------------------------
  !Weights used in formulas for interpolation 
  !--------------------------------------------
  integer :: coc1	!Used in weighted sum of cheb polynomials in Smolyak interpolation
  integer :: coc2	!coc1 is (d-1) choose 1 and coc2 is (d-1) choose 2
  
  !--------------------------------------------------------
  !Variables that hold coefficients of policy functions 
  !--------------------------------------------------------
  real(prec),dimension(d,2**(q-d)+1,N) :: CoeffsCons3	!Coeffs for 4th order polynomials for each of d dims
  real(prec),dimension(d,2**(q-d)+1,N) :: CoeffsCap3    !Coeffs for 4th order polynomials for each of d dims
  real(prec),dimension(d,2**(q-d-1)+1,N) :: CoeffsCons1	!Coeffs for 2nd order polynomials for each of d dims
  real(prec),dimension(d,2**(q-d-1)+1,N) :: CoeffsCap1	!Coeffs for 2nd order polynomials for each of d dims
  real(prec),dimension(d-1,d,2**(q-d-1)+1,2**(q-d-1)+1,N) :: CoeffsCons2 !Coeffs for 2nd order tensor prods
  real(prec),dimension(d-1,d,2**(q-d-1)+1,2**(q-d-1)+1,N) :: CoeffsCap2	 !Coeffs for 2nd order tensor prods
  real(prec),dimension(N) :: yCons0		!Policy function (consumption) evaluated at point0
  real(prec),dimension(N) :: yCap0		!Policy function (capital) evaluated at point0
  
  !--------------------------------
  !General global variables
  !--------------------------------
  real(prec),dimension(N) :: SimConsumption, SimCapTom, SimOutput
  real(prec),dimension(N) :: SimCapital, shock
  real(prec),dimension(2*N) :: instate
  real(prec),dimension(3*N) :: Results
  
contains
  
  !*************************
  !** Primative Functions **
  !*************************
  
  !-------------------------------------------------------
  ! function Ucc
  !
  !	2nd Derivative of (CRRA) utility function with
  !	coefficient of relative risk aversion 1/gamma
  !
  ! Inputs:	c -- real, consumption 
  ! Returns:	real -- U"(c) 
  !
  !-------------------------------------------------------
  
  function Ucc(c)
    implicit none
    real(prec) Ucc
    real(prec), intent(in) :: c
    real(prec) :: epsilon
    
    epsilon = (10.0)**(-6)
    
    if (c >= epsilon) then
       Ucc = -1.0/gamma * c**(-1.0/gamma - 1.0)
    else
       print*, 'c is below lower bound in the function Ucc, c = ', c	
       !pause
       Ucc = -1.0/gamma * epsilon**(-1.0/gamma - 1.0)
    end if
    
  end function Ucc
  
  !---------------------------------------------------
  ! function Uc
  !
  !	(CRRA) marginal utility function with
  !	coefficient of relative risk aversion 1/gamma
  !
  ! Inputs:	c -- real, consumption 
  ! Returns:	real, marginal utility 
  !
  !---------------------------------------------------
  
  function Uc(c)
    implicit none
    real(prec) Uc
    real(prec), intent(in) :: c
    real(prec) :: epsilon
    
    epsilon = (10.0)**(-6)
    
    if (c >= epsilon) then
       Uc = c**(-1.0/gamma)
    else
       print*, 'c is below lower bound in the function Uc, c = ', c
       pause
       Uc = epsilon**(-1.0/gamma) + Ucc(epsilon) * (c - epsilon)
    end if
    
  end function Uc
  
  !------------------------------------------------------------------------------------
  ! function F
  !
  !	Production Function - Takes country specific capital stock and 
  !	technology shock and returns output.
  !
  ! Inputs:	capital -- real, capital level
  !			sh -- real, technological shock   
  ! Returns:	real, output
  !
  !------------------------------------------------------------------------------------
  
  function F(capital,sh)
    implicit none
    real(prec) :: F
    real(prec), intent(in) :: capital, sh
    real(prec) :: epsilon
    
    epsilon = (10.0)**(-6)
    
    if (capital >= epsilon) then
       F =  A_tfp * exp(sh)*capital**alpha
    else
       print*, "Error - Capital Stock is negative in F, cap = ", capital 
       pause
       F = 0
    end if
    
  end function F
  
  !----------------------------------------------------------------------------
  ! function Fk
  !
  !	Marginal Product of Capital - Takes country specific capital stock and 
  !	technology shock and returns mpk.
  !
  ! Inputs:	capital -- real, capital level
  !			sh -- real, technological shock   
  ! Returns:	real, mpk
  !
  !----------------------------------------------------------------------------
  
  function Fk(capital,sh)
    implicit none
    real(prec) :: Fk
    real(prec), intent(in) :: capital,sh
    real(prec) :: epsilon
    
    epsilon = (10.0)**(-6)
    
    if (capital >= epsilon) then
       Fk =  A_tfp * alpha*exp(sh)*capital**(alpha-1.0)
    else
       print*, "Error - Capital Stock is negative in Fk, cap = ", capital  
       pause
       Fk =  A_tfp * alpha*exp(sh)*epsilon**(alpha-1.0)
    end if
    
  end function Fk
    
end module Params
