#Metview Macro

#  **************************** LICENSE START ***********************************
# 
#  Copyright 2017 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      : flexpart_total_column
#
# Syntax        : fieldset flexpart_total_column (source: string,
#                                          data:  fieldset,
#                                          param: string,                                                                                                                 
#                                          top_level: number,
#                                          bottom_level: number,
#                                          step: number, 
#                                          release: number,                                          
#                                          ageclass: number)
#
# Category      : FLEXPART
#
# OneLineDesc   : Computes the sum/vertical integral of fields in a FLEXPART output GRIB file. 
#
# Description   : 
#
# Parameters    : source - the FLEXPART output GRIB file                
#                 data - The FLEXPART output GRIB as a fieldset. 
#                        It takes precedence over source
#                 param -  the shortname of the GRIB parameter. If param
#                          is "mdc" (mass density concentration) the column
#                          integrated mass is computed. Otherwise the fields
#                          are simply added up for the specified level range. 
#                 top_level - The top height level (inclusive) for the computations. Optional.
#                 top_level - The top height level (inclusive) for the computations. Optional.
#                 step  - the forecast steps to extract
#                 release - the releases to extract. Release indexing starts at 1. 
#                 ageclass - the ageclasses to extract. Ageclass indexing starts at 1. 
#
# Return Value  : fieldset
#
# Dependencies  : none
#
# Example Usage : 
#                 
#
# **************************************************************************


function flexpart_total_column

    ARG=arguments()

    if mod(count(ARG),2) <> 0 then
        fail("incorrect number of arguments are specified!")
    end if        
     
    #print(ARG) 
     
    data=nil
    inFile=""
    param=""
    levType="hl"
    top=-1
    bottom=-1
    step=-1E18
    release=-1
    ageclass=-1
       
    for i=1 to count(ARG) by 2 do
        
        key=lowercase(ARG[i])
        val=ARG[i+1]
        
        if key = "data" then
            data=val
            if type(data) <> "fieldset" then
                fail("Invalid argument specified for data!")
            end if 
            if data = nil then
                fail("Invalid fieldset specified for data!")
            end if     
        else if key = "source" then
            inFile=val  
        else if key = "param" then
            param=val 
        else if key = "top_level" then
            top=val          
        else if key = "bottom_level" then
            bottom=val           
        else if key = "step" then
            step = val
        else if key = "release" then
            release = val        
        else if key = "ageclass" then
            ac = val   
        end if                  
    
    end for   
    
    if param = "" then
        fail("No param is defined!")
    end if    
    
    #Read file
    if data = nil then
        if length(inFile) > 0 and inFile <> "" then     
            data=read(inFile)
        else
            return nil
        end if    
    end if    
             
    #Get the available list of levels    
    stepLev=grib_get_long(data[1],"step")
    gLev=flexpart_filter(data: data,
                      param: param,
                      levType: "hl",
                      step: stepLev,
                      release: 1,
                      ageclass: 1
                      )                     
    levLst=nil        
    loop f in  gLev      
        levLst=levLst & [grib_get_long(f,"level")]
    end loop    
    levLst=sort(unique(levLst))
  
    #select the level range
    if top > 0 then
       tmpLevLst=levLst
       levLst=nil
       loop v in tmpLevLst
            if v <= top then
                levLst=levLst & [v]
            end if
       end loop         
    end if
    
    if bottom >= 0 then
       tmpLevLst=levLst
       levLst=nil
       loop v in tmpLevLst
            if v > bottom then
                levLst=levLst & [v]
            end if
       end loop         
    end if
    
    print("levels=",levLst)
    res=nil
    if param =  "mdc" then
    
        #compute the difference between the levels (in m)
        dLevLst=nil
        for lev=1 to count(levLst) do
            if lev = 1 then
                v=levLst[1]
            else    
                v=levLst[lev]-levLst[lev-1]
            end if
            dLevLst=dLevLst & [v]
        end for    
      
        #print (dLevLst)  
        
        res=nil    
        for lev=1 to count(levLst) do        
        
            f=flexpart_filter(data: data,
                    param: param,
                    levType: "hl",
                    level: levLst[lev],
                    step: step,
                    release: release,
                    ageclass: ageclass)
                    
            if lev = 1 then
                res=f*dLevLst[lev]
            else           
                res=res + f*dLevLst[lev]
            end if
        end for
    else
        res=nil    
        for lev=1 to count(levLst) do        
        
            f=flexpart_filter(data: data,
                    param: param,
                    levType: "hl",
                    level: levLst[lev],
                    step: step,
                    release: release,
                    ageclass: ageclass)
            
            print(f)
            
            if res = nil then
               res=f
            else        
                res=res + f
            end if    
        end for   
    
    end if
    
    if param = "mdc" then
        res=grib_set_string(res,["shortName","tcmd","typeOfLevel","sfc"])
    else
        res=grib_set_string(res,["typeOfLevel","sfc"])
    end if
    res=grib_set_long(res,["generatingProcessIdentifier",128,"level",0])
    
    return res

end flexpart_total_column

