#Metview Macro

#  **************************** LICENSE START ***********************************
# 
#  Copyright 2021 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 ************************************
# 

# **************************************************************************
# Computes the static stability
#
# OneLineDesc   : Computes the static stability              
#
# **************************************************************************


function static_stability

    _fn_name = "static_stability"
    
    _args = arguments()
    
    if count(_args) < 1 then 
        fail(_fn_name & ": too few arguments specified!")
    end if
    
    _kwargs_idx = 2
    _t = _args[1]
    _p = nil
    if count(_args) >= 2 then
        if type(_args[2]) <> "string" then
            _p = _args[2]
            _kwargs_idx = 3
        end if
    end if
    
    # keyword args
    _opt = (layer: "off")
    _opt = __get_kwargs(_fn_name, _args, _kwargs_idx, _opt)
    _layer = _opt.layer
   
    _has_pl_fields = 0
    if _p = nil then
        _p = __get_pressure_from_pl_arg(_t, "t", _fn_name)   
    end if

    Rd = 287.0597 # gas constant
    KAPPA=0.285691 #Rd/cp
  
    if count(_p) < 2 then
        fail(_fn_name  & ":number of levels (=" & count(_p) & ") must be >=2")
    end if

    if type(_t) = "fieldset" then
        v = __prepare_pressure_field_arg(_t, _p, "t", _fn_name)
        _p = v[1]
        _has_pl_fields = v[2]
    end if     

    if _layer = "off" then
        if _has_pl_fields = 1 then
            _dt = pressure_derivative(_t)
        else
            _dt = pressure_derivative(_t, _p) 
        end if
       
        if type(_t) = "fieldset" and _has_pl_fields = 1 then
            r = nil
            for i=1 to count(_t) do
                r = r & ((KAPPA*Rd/(_p[i]^2))*_t[i] - (Rd/_p[i])*_dt[i])
            end for
        else
            r = (KAPPA*Rd/(_p^2))*_t - (Rd/_p)*_dt
        end if
    end if
    
    # cannot use else here due to limitations in macro language
    if  _layer <> "off" then
         if count(_t) <> 2 or count(_p) <> 2 then
             fail(_fn_name & ": when layer mode is enabled the number of fields/values must be 2")
         end if
        
        _tm = mean(_t)
        _pm = mean(_p)    
        _dt = (_t[1] - _t[2])/(_p[1] - _p[2])
        r = (KAPPA*Rd/(_pm^2))*_tm - (Rd/_pm)*_dt  
        
        # for pressure level data make sure the pressure
        # of the upper level is encoded into the result
        if type(_t) = "fieldset" and _has_pl_fields then
            _p_upper = _p[2]
            if _p[1] < _p[2] then
                _p_upper = _p[1]
            end if
            r = grib_set_long(r, ["level", _p_upper/100])
        end if
    end if
        
    return r
end static_stability    
    

