#Metview Macro

#  **************************** LICENSE START ***********************************
# 
#  Copyright 2019 ECMWF. This software is distributed under the terms
#  of the Apache License version 2.0. In applying this license, ECMWF does not
#  waive the privileges and immunities granted to it by virtue of its status as
#  an Intergovernmental Organization or submit itself to any jurisdiction.
# 
#  ***************************** LICENSE END ************************************
# 

#=============================================================================
# Function      : lifted_condensation_level
#
# Syntax        : definition lifted_condensation_level(t: number, p: number)
#                                          
# Category      : THERMODYNAMICS
#
# OneLineDesc   : Computes the Lifted Condensation Level (LCL) using the parcel method
#
# Description   : Compute the Lifted Condensation Level (LCL) using the parcel method
#
# Parameters    : t - the start temperature of the parcel (K)
#                 td - the start dewpoint temperature of the parcel (K) 
#		 		  p - the start pressure of the parcel (Pa)
#           
# Return Value  : definition (t, p) where t is the temperature (K) and p (Pa) is the
#                 pressure of the LCL. If the LCL cannot be computed or does not exist
#                 nil is returned.
#
# Dependencies  : none
#
#==============================================================================

function lifted_condensation_level(t: number, td: number, p: number)

    fn_name = "lifted_condensation_level:"
    
    # check values/units
    if t < 60 then
    	print(fn_name," invalid temperature=",t," K")
    	return nil
  	end if
  	
  	if td < 60  then  	
    	print(fn_name," invalid dew point=",td," K")
  	end if
    
    if p < 1200 then  	
    	print(fn_name," invalid pressure=",p," Pa")
  	end if
    
    t_lcl = 0.0
    p_lcl = p  
    dp = 25000 # 25 hPa

	# we do not compute the LCL if the start is above 280 hPa
    if  p <= 28000 then
    	p_lcl = 28000
    	dp = p/2  
    end if	
    
    iter_num=20
    eps=1E-4

    # saturation mixing ratio for dewpoint ( the target mixing ratio)
    mr_target = saturation_mixing_ratio(td,p)
    if mr_target <= 0 then
        return nil
	end if
	
    # potential temperature for the dry adiabat
    th=potential_temperature(t,p)

    # iterate along the dry adabat
    for i=1 to iter_num do
    
        # the temperature at pressure p_lcl
        t_lcl = temperature_from_potential_temperature(th,p_lcl)

        # the ratio of the current saturation mixing ratio and the target
        r = saturation_mixing_ratio(t_lcl,p_lcl)/mr_target

        # check convergence and adjust pressure
        if abs(r-1.0) < eps then
            return (t: t_lcl, p: p_lcl)
        else if r > 1.0 then
            p_lcl = p_lcl - dp
        else
            p_lcl = p_lcl + dp
		end if
		
        if p_lcl <=0 or p_lcl > p then
            return nil
		end if
		
        # decrease pressure delta as we converge
        dp = dp / 2.0;
    end for

    # we are below the starting height
    if p_lcl > p then  
        p_lcl = p
        t_lcl = t
    end if

    return (t: t_lcl, p: p_lcl)

end lifted_condensation_level