!***********************************************************************************
!	MODULE:	StaticFOC
!
!	PURPOSE: Contains subroutines ConsLabOne & ConsLabOther, AConsLabOne &
!		  AConsLabOther, FConsLabOne & FConsLabOther 
!
!	AUTHOR:	Ben Malin
!
!	DATE:	7/2004
!       REVISED: 8/3/2007
!***********************************************************************************

module StaticFOC
  
  use Params

  implicit none
  
contains
  
  !***********************************************************************************
  !
  !	SUBROUTINE:  ConsLabOne
  !
  !	PURPOSE: Specifies equation whose solution is the labor supply of country 1.
  !
  !	AUTHOR:	 Ben Malin 
  !
  !	DATE:    7/2004
  !     REVISED: 7/17/2007
  !
  !***********************************************************************************

  subroutine ConsLabOne(ls,mrsmpl,countA)
    
    ! inputs:
    !    ls -- Holds guess of nonlinear equation solver
    !    countA -- size of pol vector -- 1
    !
    ! output:
    !    mrsmpl -- value of equation evaluated at ls
    ! 
    ! remarks:
    !    ls(1) will be the labor supply of country 1.
    !
    
    use Params

    implicit none
        
    !Variable Declaration
    integer,intent(in) :: countA	
    real(prec),dimension(countA),intent(in) :: ls	
    real(prec),dimension(countA),intent(out) :: mrsmpl
    
    real(prec) :: epsilon = 10.0**(-6)
    real(prec), dimension(countA) :: lstemp
    real(prec) :: BigNumb = 100
    
    !Iter2 keeps track of the number of iterations of the nle solver 
    iter2 = iter2+1
  
    !Make sure nle solver's guess for labor supply is in-bounds
    if (ls(1) < epsilon) then
       print*, 'error: labor supply below epsilon in ConsLabOne', iter2, stind
       pause
       lstemp(1) = epsilon    !Sets labor supply at the boundary
    elseif (ls(1) > Le) then
       print*, 'error: labor supply above endowment in ConsLabOne ', iter2, stind
       pause
       lstemp(1) = Le - epsilon   !Sets labor supply near boundary
    else
       lstemp(1) = ls(1)
    endif
    
    mrsmpl = UlUc(EECons(1),lstemp(1),1) + FL(k(stind(1),1),lstemp(1),z(stind(N+1),1),1)

    !Penalty if guess for labor supply is out-of-bounds
    if (ls(1) < epsilon) then
       !print*, mrsmpl(1)
       mrsmpl(1) = mrsmpl(1) - (ls(1) - epsilon) * BigNumb
       !print*, mrsmpl(1), ls(1)
    elseif (ls(1) > Le) then
       !print*, mrsmpl(1)
       mrsmpl(1) = mrsmpl(1) - (ls(1) - Le + epsilon) * BigNumb
       !print*, mrsmpl(1), ls(1)
    endif

  end subroutine ConsLabOne

  !***********************************************************************************
  !
  !	SUBROUTINE:  ConsLabOther
  !
  !	PURPOSE: Specifies system of 2 equations whose solution is the labor supply
  !               and consumption of country i.
  !
  !	AUTHOR:	 Ben Malin 
  !
  !	DATE:    7/2004
  !     REVISED: 7/17/2007
  !
  !***********************************************************************************

  subroutine ConsLabOther(polcl,StatFOC,countB)
    
    ! inputs:
    !    polcl -- Holds guess of nonlinear equation solver
    !    countB -- size of polcl vector -- 1
    !
    ! output:
    !    StatFOC -- value of equations evaluated at polcl
    ! 
    ! remarks:
    !    polcl(1) will be consumption of country i
    !    polcl(2) will be the labor supply of country i
    !
    
    use Params

    implicit none
        
    !Variable Declaration
    integer,intent(in) :: countB    !countB == 2
    real(prec),dimension(countB),intent(in) :: polcl	
    real(prec),dimension(countB),intent(out) :: StatFOC
    
    real(prec) :: epsilon = 10.0**(-6)
    real(prec), dimension(countB) :: poltemp
    real(prec) :: BigNumb = 100
    
    !Iter2 keeps track of the number of iterations of the nle solver 
    iter2 = iter2+1
  
    !Make sure nle solver's guesses for labor supply and consumption are in-bounds
    poltemp(1) = exp(polcl(1))
    poltemp(2) = exp(polcl(2))
    if (poltemp(2) > Le - epsilon) then
       print*, 'error: labor supply above endowment in ConsLabOther', iter2, stind
!       pause
       poltemp(2) = Le - epsilon    !Sets labor supply at the boundary
    endif
    
    !FOC for consumption smoothing
    StatFOC(1) = Pareto(1) * Uc(EECons(1),EELab(1),1) - Pareto(FOCi) * Uc(poltemp(1),poltemp(2),FOCi)

    !FOC for labor supply
    StatFOC(2) = UlUc(poltemp(1),poltemp(2),FOCi) + FL(k(stind(FOCi),FOCi),poltemp(2),z(stind(N+FOCi),FOCi),FOCi)

    !Penalty if guess for labor supply is out-of-bounds
    if (poltemp(2) > Le - epsilon) then
       StatFOC(2) = StatFOC(2) - (poltemp(2) - Le + epsilon)*BigNumb
    endif

  end subroutine ConsLabOther

  !***********************************************************************************
  !
  !	SUBROUTINE:  AConsLabOne
  !
  !	PURPOSE: Specifies equation whose solution is the labor supply of country 1.
  !
  !	AUTHOR:	 Ben Malin 
  !
  !	DATE:    7/2004
  !     REVISED: 7/30/2007
  !
  !***********************************************************************************

  subroutine AConsLabOne(ls,mrsmpl,countA)
    
    ! inputs:
    !    ls -- Holds guess of nonlinear equation solver
    !    countA -- size of pol vector -- 1
    !
    ! output:
    !    mrsmpl -- value of equation evaluated at ls
    ! 
    ! remarks:
    !    ls(1) will be the labor supply of country 1.
    !
    
    use Params

    implicit none
        
    !Variable Declaration
    integer,intent(in) :: countA	
    real(prec),dimension(countA),intent(in) :: ls	
    real(prec),dimension(countA),intent(out) :: mrsmpl
    
    real(prec) :: epsilon = 10.0**(-6)
    real(prec), dimension(countA) :: lstemp
    real(prec) :: BigNumb = 100
    
    !Make sure nle solver's guess for labor supply is in-bounds
    if (ls(1) < epsilon) then
       print*, 'error: labor supply below epsilon in AConsLabOne'
       pause
       lstemp(1) = epsilon    !Sets labor supply at the boundary
    elseif (ls(1) > Le) then
       print*, 'error: labor supply above endowment in AConsLabOne '
       pause
       lstemp(1) = Le - epsilon    !Sets labor supply near boundary
    else
       lstemp(1) = ls(1)
    endif
    
    mrsmpl = UlUc(SimConsumption(sn,tc-1,1),lstemp(1),1) + &
         & FL(SimCapital(sn,tc-1,1),lstemp(1),shock(sn,tc-1,1),1)

    !Penalty if guess for labor supply is out-of-bounds
    if (ls(1) < epsilon) then
       !print*, mrsmpl(1)
       mrsmpl(1) = mrsmpl(1) - (ls(1) - epsilon) * BigNumb
       !print*, mrsmpl(1), ls(1)
    elseif (ls(1) > Le) then
       !print*, mrsmpl(1)
       mrsmpl(1) = mrsmpl(1) - (ls(1) - Le + epsilon) * BigNumb
       !print*, mrsmpl(1), ls(1)
    endif

  end subroutine AConsLabOne

  !***********************************************************************************
  !
  !	SUBROUTINE:  AConsLabOther
  !
  !	PURPOSE: Specifies system of 2 equations whose solution is the labor supply
  !               and consumption of country i.
  !
  !	AUTHOR:	 Ben Malin 
  !
  !	DATE:    7/2004
  !     REVISED: 7/30/2007
  !
  !***********************************************************************************

  subroutine AConsLabOther(polcl,StatFOC,countB)
    
    ! inputs:
    !    polcl -- Holds guess of nonlinear equation solver
    !    countB -- size of polcl vector -- 1
    !
    ! output:
    !    StatFOC -- value of equations evaluated at polcl
    ! 
    ! remarks:
    !    polcl(1) will be consumption of country i
    !    polcl(2) will be the labor supply of country i
    !
    
    use Params

    implicit none
        
    !Variable Declaration
    integer,intent(in) :: countB    !countB == 2
    real(prec),dimension(countB),intent(in) :: polcl	
    real(prec),dimension(countB),intent(out) :: StatFOC
    
    real(prec) :: epsilon = 10.0**(-6)
    real(prec), dimension(countB) :: poltemp
    real(prec) :: BigNumb = 100
    
    !Make sure nle solver's guesses for labor supply and consumption are in-bounds
    poltemp(1) = exp(polcl(1))
    if (polcl(2) < epsilon) then
       print*, 'error: labor supply below epsilon in AConsLabOther'
       pause
       poltemp(2) = epsilon    !Sets labor supply at the boundary
    elseif (polcl(2) > Le) then
       print*, 'error: labor supply above endowment in AConsLabOther'
       pause
       poltemp(2) = Le - epsilon   !Sets labor supply near boundary
    else
       poltemp(2) = polcl(2)
    endif
    
    !FOC for consumption smoothing
    StatFOC(1) = Pareto(1) * Uc(SimConsumption(sn,tc-1,1),SimLabor(sn,tc-1,1),1) & 
         & - Pareto(FOCi) * Uc(poltemp(1),poltemp(2),FOCi)

    !FOC for labor supply
    StatFOC(2) = UlUc(poltemp(1),poltemp(2),FOCi) & 
         & + FL(SimCapital(sn,tc-1,FOCi),poltemp(2),shock(sn,tc-1,FOCi),FOCi)

    !Penalty if guess for labor supply is out-of-bounds
    if (polcl(2) < epsilon) then
       !print*, StatFOC(2)
       StatFOC(2) = StatFOC(2) - (polcl(2) - epsilon) * BigNumb
       !print*, StatFOC(2), polcl(2)
    elseif (polcl(2) > Le) then
       !print*, StatFOC(2)
       StatFOC(2) = StatFOC(2) - (polcl(2) - Le + epsilon) * BigNumb
       !print*, StatFOC(2), polcl(2)
    endif

  end subroutine AConsLabOther

  !***********************************************************************************
  !
  !	SUBROUTINE:  FConsLabOne
  !
  !	PURPOSE: Specifies equation whose solution is the labor supply of country 1.
  !
  !	AUTHOR:	 Ben Malin 
  !
  !	DATE:    8/3/2007
  !     REVISED: 
  !
  !***********************************************************************************

  subroutine FConsLabOne(ls,mrsmpl,countA)
    
    ! inputs:
    !    ls -- Holds guess of nonlinear equation solver
    !    countA -- size of pol vector -- 1
    !
    ! output:
    !    mrsmpl -- value of equation evaluated at ls
    ! 
    ! remarks:
    !    ls(1) will be the labor supply of country 1.
    !
    
    use Params

    implicit none
        
    !Variable Declaration
    integer,intent(in) :: countA	
    real(prec),dimension(countA),intent(in) :: ls	
    real(prec),dimension(countA),intent(out) :: mrsmpl
    
    real(prec) :: epsilon = 10.0**(-6)
    real(prec), dimension(countA) :: lstemp
    real(prec) :: BigNumb = 100
    
    !Make sure nle solver's guess for labor supply is in-bounds
    if (ls(1) < epsilon) then
       print*, 'error: labor supply below epsilon in FConsLabOne'
!       pause
       lstemp(1) = epsilon    !Sets labor supply at the boundary
    elseif (ls(1) > Le) then
       print*, 'error: labor supply above endowment in FConsLabOne '
!       pause
       lstemp(1) = Le    !Sets labor supply at the boundary
    else
       lstemp(1) = ls(1)
    endif
    
    mrsmpl = UlUc(ExCons1,lstemp(1),1) + Fl(ktemp(1),lstemp(1),ExZ1,1)

    !Penalty if guess for labor supply is out-of-bounds
    if (ls(1) < epsilon) then
       !print*, mrsmpl(1)
       mrsmpl(1) = mrsmpl(1) - (ls(1) - epsilon) * BigNumb
       !print*, mrsmpl(1), ls(1)
    elseif (ls(1) > Le) then
       !print*, mrsmpl(1)
       mrsmpl(1) = mrsmpl(1) - (ls(1) - Le) * BigNumb
       !print*, mrsmpl(1), ls(1)
    endif

  end subroutine FConsLabOne

  !***********************************************************************************
  !
  !	SUBROUTINE:  FConsLabOther
  !
  !	PURPOSE: Specifies system of 2 equations whose solution is the labor supply
  !               and consumption of country i.
  !
  !	AUTHOR:	 Ben Malin 
  !
  !	DATE:    8/3/2007
  !     REVISED: 
  !
  !***********************************************************************************

  subroutine FConsLabOther(polcl,StatFOC,countB)
    
    ! inputs:
    !    polcl -- Holds guess of nonlinear equation solver
    !    countB -- size of polcl vector -- 1
    !
    ! output:
    !    StatFOC -- value of equations evaluated at polcl
    ! 
    ! remarks:
    !    polcl(1) will be consumption of country i
    !    polcl(2) will be the labor supply of country i
    !
    
    use Params

    implicit none
        
    !Variable Declaration
    integer,intent(in) :: countB    !countB == 2
    real(prec),dimension(countB),intent(in) :: polcl	
    real(prec),dimension(countB),intent(out) :: StatFOC
    
    real(prec) :: epsilon = 10.0**(-6)
    real(prec), dimension(countB) :: poltemp
    real(prec) :: BigNumb = 100
    
    !Make sure nle solver's guesses for labor supply and consumption are in-bounds
    poltemp(1) = exp(polcl(1))
    poltemp(2) = exp(polcl(2))
    if (poltemp(2) > Le - epsilon) then
       print*, 'error: labor supply above endowment in FConsLabOther', iter2, stind
!       pause
       poltemp(2) = Le - epsilon    !Sets labor supply at the boundary
    endif
    
    !FOC for consumption smoothing
    StatFOC(1) = Pareto(1) * Uc(ExCons1,ExLab1,1) - Pareto(FOCi) * Uc(poltemp(1),poltemp(2),FOCi)

    !FOC for labor supply
    StatFOC(2) = UlUc(poltemp(1),poltemp(2),FOCi) + FL(ktemp(FOCi),poltemp(2),ExZnc,FOCi)

    !Penalty if guess for labor supply is out-of-bounds
    if (poltemp(2) > Le - epsilon) then
       StatFOC(2) = StatFOC(2) - (poltemp(2) - Le + epsilon)*BigNumb
    endif

  end subroutine FConsLabOther

  !***********************************************************************************
  !
  !	SUBROUTINE:  DConsLabOne
  !
  !	PURPOSE: Specifies equation whose solution is the labor supply of country 1.
  !
  !	AUTHOR:	 Ben Malin 
  !
  !	DATE:    12/2009
  !
  !***********************************************************************************

  subroutine DConsLabOne(ls,mrsmpl,countA)
    
    ! inputs:
    !    ls -- Holds guess of nonlinear equation solver
    !    countA -- size of pol vector -- 1
    !
    ! output:
    !    mrsmpl -- value of equation evaluated at ls
    ! 
    ! remarks:
    !    ls(1) will be the labor supply of country 1.
    !
    
    use Params

    implicit none
        
    !Variable Declaration
    integer,intent(in) :: countA	
    real(prec),dimension(countA),intent(in) :: ls	
    real(prec),dimension(countA),intent(out) :: mrsmpl
    
    real(prec) :: epsilon = 10.0**(-6)
    real(prec), dimension(countA) :: lstemp
    real(prec) :: BigNumb = 100
    
    !Make sure nle solver's guess for labor supply is in-bounds
    if (ls(1) < epsilon) then
       print*, 'error: labor supply below epsilon in AConsLabOne'
       pause
       lstemp(1) = epsilon    !Sets labor supply at the boundary
    elseif (ls(1) > Le) then
       print*, 'error: labor supply above endowment in AConsLabOne '
       pause
       lstemp(1) = Le    !Sets labor supply at the boundary
    else
       lstemp(1) = ls(1)
    endif
    
    mrsmpl = UlUc(DecCons1,lstemp(1),1) + &
         & FL(DecCap1,lstemp(1),DecShock1,1)

    !Penalty if guess for labor supply is out-of-bounds
    if (ls(1) < epsilon) then
       !print*, mrsmpl(1)
       mrsmpl(1) = mrsmpl(1) - (ls(1) - epsilon) * BigNumb
       !print*, mrsmpl(1), ls(1)
    elseif (ls(1) > Le) then
       !print*, mrsmpl(1)
       mrsmpl(1) = mrsmpl(1) - (ls(1) - Le) * BigNumb
       !print*, mrsmpl(1), ls(1)
    endif

  end subroutine DConsLabOne
  
  !***********************************************************************************
  !
  !	SUBROUTINE:  DConsLabOther
  !
  !	PURPOSE: Specifies system of 2 equations whose solution is the labor supply
  !               and consumption of country N.
  !
  !	AUTHOR:	 Ben Malin 
  !
  !	DATE:    12/2009
  !
  !***********************************************************************************

  subroutine DConsLabOther(polcl,StatFOC,countB)
    
    ! inputs:
    !    polcl -- Holds guess of nonlinear equation solver
    !    countB -- size of polcl vector -- 1
    !
    ! output:
    !    StatFOC -- value of equations evaluated at polcl
    ! 
    ! remarks:
    !    polcl(1) will be consumption of country N
    !    polcl(2) will be the labor supply of country N
    !
    
    use Params

    implicit none
        
    !Variable Declaration
    integer,intent(in) :: countB    !countB == 2
    real(prec),dimension(countB),intent(in) :: polcl	
    real(prec),dimension(countB),intent(out) :: StatFOC
    
    real(prec) :: epsilon = 10.0**(-6)
    real(prec), dimension(countB) :: poltemp
    real(prec) :: BigNumb = 100
    
    !Make sure nle solver's guesses for labor supply and consumption are in-bounds
    poltemp(1) = exp(polcl(1))
    if (polcl(2) < epsilon) then
       print*, 'error: labor supply below epsilon in AConsLabOther'
       pause
       poltemp(2) = epsilon    !Sets labor supply at the boundary
    elseif (polcl(2) > Le) then
       print*, 'error: labor supply above endowment in AConsLabOther'
       pause
       poltemp(2) = Le    !Sets labor supply at the boundary
    else
       poltemp(2) = polcl(2)
    endif
    
    !FOC for consumption smoothing
    StatFOC(1) = Pareto(1) * Uc(DecCons1,DecLab1,1) & 
         & - Pareto(N) * Uc(poltemp(1),poltemp(2),N)

    !FOC for labor supply
    StatFOC(2) = UlUc(poltemp(1),poltemp(2),N) + FL(DecCapN,poltemp(2),DecShockN,N)

    !Penalty if guess for labor supply is out-of-bounds
    if (polcl(2) < epsilon) then
       !print*, StatFOC(2)
       StatFOC(2) = StatFOC(2) - (polcl(2) - epsilon) * BigNumb
       !print*, StatFOC(2), polcl(2)
    elseif (polcl(2) > Le) then
       !print*, StatFOC(2)
       StatFOC(2) = StatFOC(2) - (polcl(2) - Le) * BigNumb
       !print*, StatFOC(2), polcl(2)
    endif

  end subroutine DConsLabOther

end module StaticFOC
