#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      : laplacian
#
# Syntax        : fieldset laplacian(fs:fieldset)
#                                          
# Category      : DERIVATIVES
#
# OneLineDesc   : Computes horizontal Laplacian of fields
#
# Description   : Compute the horizontal Laplacian of fields defined on a 
#	              regular lat-lon grid. The computation uses a second order accuracy
#                 finite difference scheme.
#
# Parameters    : fs - fieldset 
#                 
# Return Value  : resulting fieldset
#
# Dependencies  : none
#
# Example Usage : 
#                 
#
# **************************************************************************

function laplacian
    
    _fn_name = "laplacian"
    
    _args = arguments()
    _v = __prepare_gradient_arg(_fn_name, 1, _args)
    if count(_v) <> 4 then
        fail(_fn_name & ": invalid arguments=" & _args)
    end if
    _fs = _v[1]
    _mode = _v[2]
    _pole_missing = _v[3]
    _vector_mode = _v[4]

    _res = nil
    
    # finite difference
    if _mode = "fdiff" then
    
        #radius of Earth
        _R = 6371200.0
      
        # extract metadata keys
        _keys = grib_get(_fs,["gridType","paramId"])
       
        for _i=1 to count(_fs) do
            # get metadata keys
            _grid_type = _keys[_i][1]
          
            # check if grid is regular latlon 
            if _grid_type <> "regular_ll" then
                fail("divergence: [field=",_i,"] - unsupported grid (=",_grid_type,"), implemented only for regular lat-lon grid")
            end if
        end for
              
        # compute the Laplacian
        _d1x = first_derivative_y(_fs)
        _d2x = second_derivative_x(_fs)
        _d2y = second_derivative_y(_fs)
        _res = _d2x + _d2y - _d1x*tanlat(_fs)/_R
          
    # finite element        
    else if _mode = "felem" then
        _res = regrid(data: _fs, nabla: "scalar_laplacian", nabla_poles_missing_values: _pole_missing)
    end if
    
    return _res
    
end laplacian 
