!=====================================================================
! NGCL: NCL Routines
!=====================================================================
!
! Plots - Wind Rose
! Plots - Pie Charts
! Plots - wkSpaceTime
! Plots - Taylor Diagram
! Plots - Skew-T
! Plots - Evans
!
! CPMPXY3 - 2D Coordinates Mapping
!
! Reading netCDF NC3file
! Reading GRIB GB2file
!
! Shapefile
!
! Spherical Harmonics
!
! Longitudes and Latitudes
!
! Date and Time
!
! Local Min/Max, Area/Volume Average
!
! ReGrid and Interpolation
!
! Random number
!
! Math and Statistics
! Math and Statistics - Empirical orthogonal functions
! Math and Statistics - Extreme values
! Math and Statistics - Bootstrap
!
! Earth Science - Climatology
! Earth Science - CESM
! Earth Science - Drought
! Earth Science - Meteorology
! Earth Science - Oceanography
! Earth Science - WRF
!
! others
!
!=====================================================================
!
! ~~~~~~~~~~~~~~~~~
! Plots - Wind Rose
! ~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_WindRose( vp, nWinds, wspd, wdir, nPetals, circFr, nBounds, spdBounds, clrBounds )
!
! ~~~~~~~~~~~~~~~~~~
! Plots - Pie Charts
! ~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_pie_chart( vp, nsections, percent, cname, icolor,&
!                          opt_label     ,&
!                          opt_label_mkid,&
!                          opt_label_htsc,&
!                          opt_title     ,&
!                          opt_title_htsc,&
!                          opt_title_yoff )
!
! ~~~~~~~~~~~~~~~~~~~
! Plots - wkSpaceTime
! ~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_wkSpaceTime( nlon, nlat, ntim, x, xmsg, spd, nDayWin, nDaySkip,&
!                            varName, pltName, pltTitle,&
!                            opt_pltTitle_sc,&
!                            opt_output_ps,&
!                            opt_output_gif,&
!                            opt_pltColorMap,&
!                            opt_cnLinesOn,&
!                            opt_Fig_1,&
!                            opt_Fig_2,&
!                            opt_Fig_3a,&
!                            opt_Fig_3b,&
!                            opt_CPGRWS,&
!                            opt_AREDAM,&
!                            opt_ARSCAM )
!
! ~~~~~~~~~~~~~~~~~~~~~~
! Plots - Taylor Diagram
! ~~~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_taylor_metrics_table( vp, nvar, nseason, ncase, vars,&
!                                     seasons, cases, values, colors,&
!                                     opt_title,&
!                                     opt_bound )
!
! SUBROUTINE ng_taylor_diagram( vp, nvar, ncase, ratio, cc, marker, color,&
!                               opt_sc_mark,&
!                               opt_sc_clab,&
!                               opt_sc_yoff,&
!                               opt_centerDiffRMS, &
!                               opt_centerDiffRMS_color,&
!                               opt_stnRad,&
!                               opt_stnRad_color,&
!                               opt_ccRays,&
!                               opt_ccRays_color,&
!                               opt_caseLabels,&
!                               opt_caseLabels_htsc,&
!                               opt_caseLabels_xloc,&
!                               opt_caseLabels_yloc,&
!                               opt_varLabels,&
!                               opt_varLabels_htsc,&
!                               opt_varLabels_xloc,&
!                               opt_varLabels_yloc,&
!                               opt_tiMainString )
!
! SUBROUTINE ng_taylor_diagram_cam( vp, nvar, ncase, ratio, cc, bias, color,&
!                                   opt_sc_mark,&
!                                   opt_sc_clab,&
!                                   opt_sc_yoff,&
!                                   opt_centerDiffRMS, &
!                                   opt_centerDiffRMS_color,&
!                                   opt_stnRad,&
!                                   opt_stnRad_color,&
!                                   opt_ccRays,&
!                                   opt_ccRays_color,&
!                                   opt_caseLabels,&
!                                   opt_caseLabels_htsc,&
!                                   opt_caseLabels_xloc,&
!                                   opt_caseLabels_yloc,&
!                                   opt_varLabels,&
!                                   opt_varLabels_htsc,&
!                                   opt_varLabels_xloc,&
!                                   opt_varLabels_yloc,&
!                                   opt_biasLabels_htsc,&
!                                   opt_biasLabels_xloc,&
!                                   opt_biasLabels_yloc,&
!                                   opt_tiMainString )
!
! ~~~~~~~~~~~~~~
! Plots - Skew-T
! ~~~~~~~~~~~~~~
!
! SUBROUTINE ng_skewT_BackGround( vp, bkcolor,&
!                                 opt_DrawColAreaFill   ,&
!                                 opt_DrawColLine       ,&
!                                 opt_DrawIsotherm      ,&
!                                 opt_DrawIsobar        ,&
!                                 opt_DrawMixRatio      ,&
!                                 opt_DrawDryAdiabat    ,&
!                                 opt_DrawMoistAdiabat  ,&
!                                 opt_DrawStandardAtm   ,&
!                                 opt_DrawStandardAtmThk,&
!                                 opt_DrawWind          ,&
!                                 opt_DrawHeightScale   ,&
!                                 opt_DrawHeightScaleFt ,&
!                                 opt_DrawFahrenheit    ,&
!                                 opt_tiMainString       )
!
! SUBROUTINE ng_skewT_PlotData( n, p, tc, tdc, z, wspd, wdir, spv, color, lwsc, dash,&
!                               opt_ThermoInfo     ,&
!                               opt_Parcel         ,&
!                               opt_Cape           ,&
!                               opt_PrintZ         ,&
!                               opt_PlotWindP      ,&
!                               opt_hemisphere     ,&
!                               opt_WspdWdir       ,&
!                               opt_Wthin          ,&
!                               opt_xpWind         ,&
!                               opt_PlotWindH      ,&
!                               opt_Height         ,&
!                               opt_Hspd           ,&
!                               opt_Hdir           ,&
!                               opt_HspdHdir        )
!
! ~~~~~~~~~~~~~
! Plots - Evans
! ~~~~~~~~~~~~~
!
! SUBROUTINE ng_evans_plotdata( n, hue_data, sat_data, spv, nhue, nsat,&
!                               hue_levels, sat_levels, var_plot )
!
! SUBROUTINE ng_evans_colormap( nhue, nsat, ColorMap,&
!                               opt_NumMaxSat,&
!                               opt_SatMin   ,&
!                               opt_ValMin   ,&
!                               opt_HueOffset,&
!                               opt_HueCyclic,&
!                               opt_RevHue   ,&
!                               opt_RevSat    )
!
! SUBROUTINE ng_evans_labelbar( vl, vr, vb, vt, nhue, nsat, cmap,&
!                               hue_labels, sat_minmax,&
!                               opt_hue_units,&
!                               opt_sat_units,&
!                               opt_hsfb     ,&
!                               opt_wsfb     ,&
!                               opt_htsc      )
!
! SUBROUTINE ng_evans_colorwheel( cx, cy, cs, nhue, nsat, cmap,&
!                                 hue_labels, sat_minmax,&
!                                 opt_title,&
!                                 opt_htsc  )
!
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! CPMPXY3 - 2D Coordinates Mapping
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE NG_CPMPXY3_INIT(X2D, Y2D, NX, NY)
! SUBROUTINE NG_CPMPXY3(IMAP, XINP, YINP, XOUT, YOUT)
! SUBROUTINE NG_CPMPXY3_FREE()
!
! SUBROUTINE NG_CPMPXY3MAP_INIT(XLON, YLAT, NLON, NLAT)
! SUBROUTINE NG_CPMPXY3MAP(IMAP, XINP, YINP, XOUT, YOUT)
! SUBROUTINE NG_CPMPXY3MAP_FREE()
!
! ~~~~~~~~~~~~~~~~~~~~~~
! Reading netCDF NC3file
! ~~~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE NG_NC32TXT( nc3file, idata )
!
! SUBROUTINE NG_NC3INIT( nc3file ) ! Open/Allocate/Header
! SUBROUTINE NG_NC3RDCH( cvar, charray, n, ier ) ! ier=1/2 for incorrect cvar/n
! SUBROUTINE NG_NC3RDI1( cvar, i1array, n, ier )
! SUBROUTINE NG_NC3RDI2( cvar, i2array, n, ier )
! SUBROUTINE NG_NC3RDI4( cvar, i4array, n, ier )
! SUBROUTINE NG_NC3RDR4( cvar, r4array, n, ier )
! SUBROUTINE NG_NC3RDR8( cvar, r8array, n, ier )
! SUBROUTINE NG_NC3FREE() ! De-allocate/Close
!
! SUBROUTINE ng_nc3varb_lonlat( nc3file, nvb, npt )
!
! ~~~~~~~~~~~~~~~~~~~~
! Reading GRIB GB2file
! ~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE NG_GB22TXT( gb2file )
!
! SUBROUTINE NG_GB2READ( gb2file, PDT_Number, PDT_Len, PDT_Array, n, gb2data,&
!                        GDT_Number, GDT_Len, GDT_Array, Missing_Value )
!
! SUBROUTINE ng_g2GDSLCGrid( GDT_Number, GDT_Len, GDT_Array, nlon, nlat, xlon2d, ylat2d,&  ! GDT3.30: Lambert conformal
!                            LatParallel1, LatParallel2,& LonMeridian )
!
! SUBROUTINE ng_g2GDSSTGrid( GDT_Number, GDT_Len, GDT_Array, nlon, nlat, xlon2d, ylat2d,&  ! GDT3.20: Polar Stereographic
!                            CenterLat, CenterLon )
!
! SUBROUTINE ng_g2GDSCEGrid( GDT_Number, GDT_Len, GDT_Array, nlon, nlat, xlon, ylat )      ! GDT3.0: Cylindrical Equidistant
!
! SUBROUTINE ng_g2GDSRLLGrid(GDT_Number, GDT_Len, GDT_Array, nlon, nlat, xlon2d, ylat2d,&  ! GDT3.1: Rotate Cylindrical Equidistant
!                            Lon_of_SouthPole, Lat_of_SouthPole, Ang_of_Rotation )
!
! ~~~~~~~~~
! Shapefile
! ~~~~~~~~~
!
! SUBROUTINE NG_DBF2TXT(DBFfile)
! SUBROUTINE NG_SHP2TXT(SHPfile)
! SUBROUTINE NG_SHX2TXT(SHXfile)
!
! SUBROUTINE ng_shp_get_n  (DBFfile, nrec, ncol)
! SUBROUTINE ng_shp_get_box(SHPfile, shapetype, minlon, maxlon, minlat, maxlat)
!
! SUBROUTINE ng_shp_get_col(DBFfile, icol, attrib, nrec)
!
! SUBROUTINE ng_shp_get_xy1(SHPfile, xlon, ylat, nrec)
!
! SUBROUTINE ng_shp_get_xyp(SHPfile, SHXfile, irec, xlon, ylat, n, list, m, npoints, nparts)
!
! SUBROUTINE ng_shp_add_polymarkers  (shapefile, color, nrec, imarker, ht, dg)
!
! SUBROUTINE ng_shp_add_polylines    (shapefile)
! SUBROUTINE ng_shp_add_polylines2   (shapefile, color, nrec)
!
! SUBROUTINE ng_shp_add_polygons     (shapefile, color, nrec)
! SUBROUTINE ng_shp_add_polygons_ave (shapefile, nlon, nlat, xlon, ylat, data,&
!                                     shpmask, nrec, clevl, color, nclv, spv, spvcolor)
!
! SUBROUTINE ng_shp_create_mask (shapefile, nlon, nlat, xlon, ylat, mask)
! SUBROUTINE ng_shp_create_mask2(shapefile, nlon, nlat, xlon, ylat, mask, shpmask, nrec)
! SUBROUTINE ng_shp_create_mask3(shapefile, nlon, nlat, xlon, ylat, mask, delta_kilometer)
!
! SUBROUTINE ng_shp_create_2dmask (shapefile, nlon, nlat, xlon, ylat, mask)
! SUBROUTINE ng_shp_create_2dmask2(shapefile, nlon, nlat, xlon, ylat, mask, shpmask, nrec)
!
! LOGICAL FUNCTION ng_gc_inout(plat, plon, qlat, qlon, npts)
!
! SUBROUTINE ng_landsea_mask(basemap, nlon, nlat, tlon, tlat, maskarray)
!
! ~~~~~~~~~~~~~~~~~~~
! Spherical Harmonics
! ~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_lderuvg(nlon, nlat, u, v, uy, vy)
! SUBROUTINE ng_lderuvf(nlon, nlat, u, v, uy, vy)
!
! SUBROUTINE ng_gradsg(nlon, nlat, z, gzx, gzy)
! SUBROUTINE ng_gradsf(nlon, nlat, z, gzx, gzy)
!
! SUBROUTINE ng_lapsg(nlon, nlat, z, zlap)
! SUBROUTINE ng_lapsf(nlon, nlat, z, zlap)
!
! SUBROUTINE ng_lapvg(nlon, nlat, u, v, ulap, vlap)
! SUBROUTINE ng_lapvf(nlon, nlat, u, v, ulap, vlap)
!
! SUBROUTINE ng_igradsg(nlon, nlat, gzx, gzy, z)
! SUBROUTINE ng_igradsf(nlon, nlat, gzx, gzy, z)
!
! SUBROUTINE ng_ilapsg(nlon, nlat, zlap, zlmbda, z)
! SUBROUTINE ng_ilapsf(nlon, nlat, zlap, zlmbda, z)
!
! SUBROUTINE ng_ilapvg(nlon, nlat, ulap, vlap, u, v)
! SUBROUTINE ng_ilapvf(nlon, nlat, ulap, vlap, u, v)
!
! SUBROUTINE ng_uv2vrg(nlon, nlat, u, v, vr)
! SUBROUTINE ng_uv2vrf(nlon, nlat, u, v, vr)
!
! SUBROUTINE ng_uv2dvg(nlon, nlat, u, v, dv)
! SUBROUTINE ng_uv2dvf(nlon, nlat, u, v, dv)
!
! SUBROUTINE ng_uv2vrdvg(nlon, nlat, u, v, vr, dv)
! SUBROUTINE ng_uv2vrdvf(nlon, nlat, u, v, vr, dv)
!
! SUBROUTINE ng_uv2sfvpg(nlon, nlat, u, v, sf, vp)
! SUBROUTINE ng_uv2sfvpf(nlon, nlat, u, v, sf, vp)
!
! SUBROUTINE ng_vr2uvg(nlon, nlat, vort, ur, vr)
! SUBROUTINE ng_vr2uvf(nlon, nlat, vort, ur, vr)
!
! SUBROUTINE ng_dv2uvg(nlon, nlat, dv, ud, vd)
! SUBROUTINE ng_dv2uvf(nlon, nlat, dv, ud, vd)
!
! SUBROUTINE ng_vrdv2uvg(nlon, nlat, vr, dv, u, v)
! SUBROUTINE ng_vrdv2uvf(nlon, nlat, vr, dv, u, v)
!
! SUBROUTINE ng_sfvp2uvg(nlon, nlat, sf, vp, u, v)
! SUBROUTINE ng_sfvp2uvf(nlon, nlat, sf, vp, u, v)
!
! SUBROUTINE ng_uv2vr_cfd(nlon, nlat, xlon, ylat, u, v, xmsg, iopt, rv, ier)
! SUBROUTINE ng_uv2dv_cfd(nlon, nlat, xlon, ylat, u, v, xmsg, iopt, dv, ier)
!
! ~~~~~~~~~~~~~~~~~~~~~~~~
! Longitudes and Latitudes
! ~~~~~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_lonGlobeF (mlon, xlon)
! SUBROUTINE ng_lonGlobeFo(mlon, xlon)
!
! SUBROUTINE ng_latGlobeF (nlat, ylat)
! SUBROUTINE ng_latGlobeFo(nlat, ylat)
!
! SUBROUTINE ng_latGau   (nlat, ylat)
! SUBROUTINE ng_latGau2  (nlat, ylat, ywgt)
!
! SUBROUTINE ng_latGauWgt(nlat, ywgt)
! SUBROUTINE ng_latRegWgt(nlat, ylat, ywgt, iopt)
!
! SUBROUTINE ng_lonFlip(nlon, m, xlon, varb)
! SUBROUTINE ng_lonPivot(nlon, m, pivotLon, xlon, varb)
!
! ~~~~~~~~~~~~~
! Date and Time
! ~~~~~~~~~~~~~
!
! SUBROUTINE ng_days_since( days, sinceyear, year, month, day )
! SUBROUTINE ng_hours_since( hours, sinceyear, year, month, day, hour )
!
! REAL FUNCTION ng_yyyymmdd_to_yyyyFrac( yyyymmdd, ddOffset )
! REAL FUNCTION ng_yyyymm_to_yyyyFrac( yyyymm  , mmOffset )
! REAL FUNCTION ng_yyyyddd_to_yyyyFrac( yyyyddd , ddOffset )
!
! INTEGER FUNCTION ng_day_of_weak( Year, Month, Day )
! INTEGER FUNCTION ng_days_in_month( Year, Month )
! INTEGER FUNCTION ng_day_of_year( Year, Month, Day )
! INTEGER FUNCTION ng_monthday( yyyy, ddd )
! LOGICAL FUNCTION ng_isleapyear(Year)
!
! INTEGER  FUNCTION ng_greg2juli( yyyy, mm, dd )     ! convert calendar date to Julian date
! REAL(r8) FUNCTION ng_greg2juld( yyyy, mm, dd, hr )
!
! SUBROUTINE ng_juld2greg( juld, yyyy, mm, dd, hr )  ! expand Julian date into a calendar date
! SUBROUTINE ng_juli2greg( juld, yyyy, mm, dd )
!
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Local Min/Max, Area/Volume Average
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_local_min(ni, nj, x, xmsg, cyclic, delta, ninj, xi, yj, locmin, nmin)
!
! SUBROUTINE ng_local_max(ni, nj, x, xmsg, cyclic, delta, ninj, xi, yj, locmax, nmax)
!
! SUBROUTINE ng_wgt_areaave(mx, ny, wgtx, wgty, t, tmsg, iflag, ave)
!
! SUBROUTINE ng_wgt_volave    (mx, ny, kz, wgtx, wgty, wgtz, t, tmsg, iflag, ave)
! SUBROUTINE ng_wgt_volave_ccm(mx, ny, kz, wgtx, wgty, wgtz, t, tmsg, iflag, ave)
!
! ~~~~~~~~~~~~~~~~~~~~~~~~
! ReGrid and Interpolation
! ~~~~~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_linint1(nxi, xi, fi, xmsg, icycx, iopt, nxo, xo, fo, ier)
! SUBROUTINE ng_linint2(nxi, nyi, xi, yi, fi, xmsg, icycx, iopt, nxo, nyo, xo, yo, fo, ier)
! SUBROUTINE ng_linint2_points(nxi, nyi, xi, yi, fi, xmsg, icycx, nxyo, xo, yo, fo, ier)
!
! SUBROUTINE ng_f2fsh(nlona, nlata, aa, nlonb, nlatb, bb)
! SUBROUTINE ng_f2gsh(nlona, nlata, aa, twave, nlonb, nlatb, bb)
! SUBROUTINE ng_g2fsh(nlona, nlata, aa, nlonb, nlatb, bb)
! SUBROUTINE ng_g2gsh(nlona, nlata, aa, twave, nlonb, nlatb, bb)
!
! SUBROUTINE ng_int2p(npin, ppin, xxin, xmsg, linlog, npout, ppout, xxout, ier)
! SUBROUTINE ng_sigma2hybrid(nlvi, sigi, dati, psfc, p0, intyp, nlvo, hya, hyb, sigo, dato)
!
! SUBROUTINE ng_area_conserve_remap   (plon, plat, plono, plato, plev,&
!                                      clon, clat, clono, clato, xx, xxmsg,&
!                                      nlat, nlato, bin_factor, yy)
! SUBROUTINE ng_area_conserve_remap_r4(plon, plat, plono, plato, plev,&
!                                      clon, clat, clono, clato, xx, xxmsg,&
!                                      nlat, nlato, bin_factor, yy)
!
! SUBROUTINE ng_poisson_grid_fill(xio, mx, ny, xmsg, is_cyclic, guess_type, nscan, epsx, relc, iopt)
!
! SUBROUTINE ng_area_hi2lores(mxi, nyi, xi, yi, zi, zimsg, icyc, wyi, mxo, nyo, xo, yo, zo, critpc)
!
! SUBROUTINE ng_triple2grid(kz, xi, yi, zi, zmsg, mx, ny, gx, gy, grid, ier)
!
! SUBROUTINE ng_obj_anal_ic(npts, xlon, ylat, zval, xymsg, zmsg, nscan, rscan, blend, nlon, nlat, glon, glat, gval, ier)
!
! SUBROUTINE ng_bin_sum(nz, zlon, zlat, zval, zmsg, nlon, nlat, glon, glat, gbin, gknt)
! SUBROUTINE ng_bin_avg(nz, zlon, zlat, zval, zmsg, nlon, nlat, glon, glat, gbinknt, ier)
!
! SUBROUTINE ng_smth9    (ni, nj, xi, xmsg, p, q, lwrap, xo)
! SUBROUTINE ng_smooth92d(nx, ny, zi, p, q, zo)
!
! ~~~~~~~~~~~~~
! Random number
! ~~~~~~~~~~~~~
!
! SUBROUTINE ng_generate_2d_array(data, m, n, mlow, mhgh, dlow, dhgh, iran)
!
! SUBROUTINE ng_generate_unique_indices( iarray, n )
! SUBROUTINE ng_generate_sample_indices( iarray, n, method )
!
! REAL FUNCTION ng_random_chi    ( df )
! REAL FUNCTION ng_random_gamma  ( a, r )
! REAL FUNCTION ng_random_normal ( av, sd )
! REAL FUNCTION ng_random_uniform( low, high )
! SUBROUTINE ng_random_setallseed( seed1, seed2 )
!
! ~~~~~~~~~~~~~~~~~~~
! Math and Statistics
! ~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE NG_PQSORT(X, N, KFLAG, IPERM) ! Quick sorting
!
! SUBROUTINE ng_sum       (x, npts, xmsg, xsum, nptused)                      ! sum
! SUBROUTINE ng_avg       (x, npts, xmsg, xavg, nptused)                      ! average
! SUBROUTINE ng_stddev    (x, npts, xmsg,  std, nptused)                      ! standard deviation
! SUBROUTINE ng_median    (x, npts, xmsg, xmedian, xmrange, xrange, nptused)  ! median
! SUBROUTINE ng_stat1     (x, npts, xmsg, xmean, nptused)                     ! first moment
! SUBROUTINE ng_stat2     (x, npts, xmsg, xmean, xvar, nptused)               ! first two moments
! SUBROUTINE ng_stat2_trim(x, npts, xmsg, ptrim, xmean, xvar, nptused)        ! trimmed estimates of the first two moments
! SUBROUTINE ng_stat4     (x, npts, xmsg, xmean, xvar, xskew, xkurt, nptused) ! first four moments
!
! SUBROUTINE ng_stat_dispersion(x, npts, xmsg, statx, PrintStat ) ! robust dispersion statistics
!
! SUBROUTINE ng_sum_wgt(x, npts, xmsg, wgt, iopt, xsum) ! weighted sum
! SUBROUTINE ng_avg_wgt(x, npts, xmsg, wgt, iopt, xavg) ! weighted average
!
! SUBROUTINE ng_rmsd(x, y, npts, xmsg, ymsg, xyrmsd)    ! root-mean-square-difference
!
! SUBROUTINE ng_rmvmean    (x, npts, xmsg)       ! remove series mean
! SUBROUTINE ng_rmvmed     (x, npts, xmsg)       ! remove series median
! SUBROUTINE ng_standardize(x, npts, xmsg, iopt) ! remove mean and standardize
!
! SUBROUTINE ng_runave( X, NPTS, NAVE, KOPT, XMSG ) ! unweighted running average
! SUBROUTINE ng_wgt_runave( X, NPTS, WGT, NWGT, KOPT, XMSG ) ! weighted running average
!
! SUBROUTINE ng_filwgt_normal  ( wt, nwt, sigma, itype )                     ! Normal Filter Weights
! SUBROUTINE ng_filwgts_lanczos( wt, nwt, ihp, fca, fcb, sigma, freq, resp ) ! Lanczos Filter Weights
! SUBROUTINE ng_bw_bandpass_filter( x, y, n, fca, fcb, m, dt, mzer, e )      ! Butterworth Bandpass Filter
! SUBROUTINE ng_demod_cmplx(ntim, x, frqdem, frqcut, nwt, opt, xamp, xpha)   ! complex demodulation on a time series
! SUBROUTINE ng_ezfftf( npts, x, xbar, cf ) ! FFT filtering (Fourier analysis)
! SUBROUTINE ng_ezfftb( npts, xbar, cf, x ) ! FFT filtering (Fourier synthesis)
! SUBROUTINE ng_fourier_info( nx, x, nhx, sclPha, finfo ) ! Fourier analysis, returns amplitude, phase, and percent variance
!
! SUBROUTINE ng_regline( x, y, npts, xmsg, ymsg, rcoef, yint, rstd, tval, xave, yave, nptxy ) ! simple linear regression
!
! SUBROUTINE ng_regline_stats(N, X, Y, b,&
!                             Yavg   , Yvar   , Ystd   , Xavg   , Xvar   , Xstd   ,&
!                             bstd   , Yest   , Yres   , SST    , SSR    , SSE    ,&
!                             MST    , MSR    , MSE    , MSE_dof, RSE    , RSE_dof,&
!                             F      , r2     , r      , fuv    , r2a    , F_dof  ,&
!                             F_pval , stderr , tval   , pval   , b95    , y95    ,&
!                             YMR025 , YMR975 , YPI025 , YPI975 , print_anova)
!
! SUBROUTINE ng_reg_multlin(n, m, y, ymsg, x, xmsg, c, sc) ! multiple linear regression
!
! SUBROUTINE ng_reg_multlin_stats(N, NP, Y, XP, b,&        ! multiple linear regression + confidence estimates
!                                 Yavg   , Yvar   , Ystd   , Xavg   , Xvar   , Xstd   ,&
!                                 bstd   , Yest   , Yres   , SST    , SSR    , SSE    ,&
!                                 MST    , MSR    , MSE    , MSE_dof, RSE    , RSE_dof,&
!                                 F      , r2     , r      , fuv    , r2a    , F_dof  ,&
!                                 F_pval , stderr , tval   , pval   , print_anova)
!
! SUBROUTINE ng_trend_manken(x, n, prob, trend) ! Mann-Kendall non-parametric test for monotonic trend
!
! SUBROUTINE ng_cdft_t   ( p, df, t ) ! calculate t-value given the probability and degrees of freedom
! SUBROUTINE ng_cdft_p   ( t, df, p ) ! calculate the probability given t-value and degrees of freedom
! SUBROUTINE ng_student_t( t, df, p ) ! Calculates the two-tailed probability of the Student-t distribution.
!
! SUBROUTINE ng_ttest( AVE1, VAR1, N1, AVE2, VAR2, N2, IFLAG, ALPHA, TVAL, IER )
! SUBROUTINE ng_ftest( VAR1, N1, VAR2, N2, ALPHA, IER )
! SUBROUTINE ng_rtest( R, N, PROB )
! SUBROUTINE ng_equiv_sample_size( X, NPTS, XMSG, SIGLVL, NEQV )
!
! SUBROUTINE ng_esacr( x, npts, xmsg, mxlag, acr, ier ) ! auto-correlations
! SUBROUTINE ng_esacv( x, npts, xmsg, mxlag, acv, ier ) ! auto-covariances
!
! SUBROUTINE ng_esccr ( x, y, npts, xmsg, ymsg, mxlag, ccr, ier ) ! cross-correlations
! SUBROUTINE ng_esccv ( x, y, npts, xmsg, ymsg, mxlag, ccv, ier ) ! cross-covariances
!
! SUBROUTINE ng_escorc( x, y, npts, xmsg, ymsg,        ccr, ier ) ! cross-correlation at lag 0 only
! SUBROUTINE ng_escovc( x, y, npts, xmsg, ymsg,        ccv, ier ) ! cross-covariance at lag 0 only
!
! SUBROUTINE ng_lspoly( M, X, Y, WGT, N, COEF ) ! weighted least squares polynomial fit
!
! SUBROUTINE ng_dtrend( x, npts, slope, yint )  ! remove the least squares linear trend
! SUBROUTINE ng_dtrend_quadratic( x, npts, coeff )
! SUBROUTINE ng_dtrend_msg( x, y, npts, xmsg, ymsg, iopt, ydt, slope, yint )
!
! SUBROUTINE ng_taper(n, x, p, iopt) ! apply split-cosine-bell tapering
!
! SUBROUTINE ng_specx_anal( x, nx, iopt, jave, pct, scl, spcx, frq,&      ! spectra of series
!                           df, bw, xavei, xvari, xvaro, xlag1, xslope)
! SUBROUTINE ng_specxy_anal( x, y, n, iopt, jave, pct, scl,&
!                            frq, spcx, spcy, cospc, quspc, coher, phase,&
!                            df, bw, coherp,&
!                            xavei, xvari, xvaro, xlag1, xslope,&
!                            yavei, yvari, yvaro, ylag1, yslope)
!
! SUBROUTINE ng_specx_ci( nspc, spcx, frq, xlag1, df, plow, phign, splt ) ! spectrum and confidence curves
! SUBROUTINE ng_specxy_ci( nspc, spcx, spcy, frq, xlag1, ylag1, df, plow, phigh, splt )
!
! REAL FUNCTION ng_chiinv( p, df ) ! inverse chi-squared distribution
!
! SUBROUTINE ng_wavelet(n, y, mother, dt, param, s0, dj, jtot, npad,&
!                       noise, isigtest, siglvl, nadof, wave,&
!                       power, phase, mean, stdev, lag1, r1, dof, scale,&
!                       period, gws, coi, fft_theor, signif, cdelta, psi0) ! the wavelet transform
!
! SUBROUTINE ng_pdfx( nx, x, xmsg, nbins, bin_bounds, pdf )
! SUBROUTINE ng_pdfxy( nxy, x, y, xmsg, ymsg, nbinx, nbiny, binx_bounds, biny_bounds, pdf )
! SUBROUTINE ng_pdfxy_conform( nx, x, xmsg, ny, y, ymsg, nbinx, nbiny, binx_bounds, biny_bounds, pdf )
!
! SUBROUTINE ng_center_finite_diff(npts, q, r, qmsg, rcyc, dqdr)
!
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Math and Statistics - Empirical orthogonal functions
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_eofunc(npts, ntim, data, dmsg, neval, jopt, evec, eval, epcv, evec_ts)
! SUBROUTINE ng_eofunc_ts(npts, ntim, data, dmsg, neval, evec, jopt, evec_ts, ts_mean)
! SUBROUTINE ng_eof2data(neval, npts, ntim, ev, evts, xmsg, x)
! SUBROUTINE ng_eofunc_varimax(npts, neval, evec, eval, epcv, emsg, iopt, evec_rot, rot_var, rot_pcv)
! SUBROUTINE ng_eofunc_varimax_reorder(npts, neval, evec_rot, rot_pcv, rot_var)
! SUBROUTINE ng_eofunc_north(neval, eval, ntim, prinfo, sig)
!
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Math and Statistics - Extreme values
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_extval_mlegev (n, x, xmsg, iopt, vals)
! SUBROUTINE ng_extval_mlegam (n, x, xmsg, iopt, vals)
! SUBROUTINE ng_extval_gev    (n, x, shape, scale, center,        iopt, pdf, cdf)
! SUBROUTINE ng_extval_gumbel (n, x, scale,        center,        iopt, pdf, cdf)
! SUBROUTINE ng_extval_frechet(n, x, shape, scale, center,        iopt, pdf, cdf)
! SUBROUTINE ng_extval_pareto (n, x, shape, scale, center, itype, iopt, pdf, cdf)
! SUBROUTINE ng_extval_weibull(n, x, shape, scale, center,        iopt, pdf, cdf)
! SUBROUTINE ng_extval_recurrence_table(n, time, x, dims, iopt, table)
! SUBROUTINE ng_extval_return_period(Tr, Pr, Nr)
! SUBROUTINE ng_extval_return_prob  (Tr, Nr, Pr)
!
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Math and Statistics - Bootstrap
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_bootstrap_correl(n, x, y, nBoot, Boot, BootAvg, BootStd,&
!                                opt_sample_size, opt_rseeds, opt_rclock,&
!                                opt_sequential)
! SUBROUTINE ng_bootstrap_diff(nx, ny, x, y, nBoot, Boot, BootAvg, BootStd,&
!                              opt_sample_size_x, opt_sample_size_y,&
!                              opt_rseeds, opt_rclock, opt_sequential)
! SUBROUTINE ng_bootstrap_estimate(nBoot, xBoot, fpc, opt, val)
! SUBROUTINE ng_bootstrap_regcoef(n, x, y, nBoot, Boot, BootAvg, BootStd,&
!                                 opt_sample_size, opt_rseeds, opt_rclock,&
!                                 opt_sequential)
! SUBROUTINE ng_bootstrap_stat(n, x, istat, nBoot, Boot, BootAvg, BootStd,&
!                              opt_sample_size, opt_sample_method,&
!                              opt_rseeds, opt_rclock, opt_sequential)
!
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Earth Science - Climatology
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_clmMon     (ntim, x, xmsg, clm)       ! monthly means (climatology)
! SUBROUTINE ng_stdMon     (ntim, x, xmsg, std)       ! monthly standard deviations
! SUBROUTINE ng_calcMonAnom(ntim, x, xmsg, clm, anom) ! monthly anomalies
!
! SUBROUTINE ng_clmDay     (ntim, yyyyddd, x, xmsg, clm)       ! daily means (climatology)
! SUBROUTINE ng_smthClmDay (clm, xmsg, nHarm, clmsm)           ! smooth daily means
! SUBROUTINE ng_calcDayAnom(ntim, yyyyddd, x, xmsg, clm, anom) ! daily anomalies
!
! SUBROUTINE ng_month_to_annual  (nloc, nyrs, xmon, xspv, iopt, xann) ! turn monthly values to annual values
! SUBROUTINE ng_month_to_season  (npts, ntim, xmon, csea, xsea)
! SUBROUTINE ng_month_to_season12(npts, ntim, xmon, xsea)
! SUBROUTINE ng_month_to_seasonN (npts, ntim, xmon, nsea, csea, xsea)
!
! ~~~~~~~~~~~~~~~~~~~~
! Earth Science - CESM
! ~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_pres_hybrid_ccm (mlon, nlat, psfc, pmsg, p0, klev, hya, hyb, phy)
! SUBROUTINE ng_dpres_hybrid_ccm(mlon, nlat, psfc, pmsg, p0, klev, hya, hyb, dphy)
!
! SUBROUTINE ng_vinth2p      (nlon, nlat, nlevi, dati, psfc, spvl, p0,            &
!                             hbcofa, hbcofb, intyp, kxtrp,         nlevo, plevo, dato)
! SUBROUTINE ng_vinth2p_ecmwf(nlon, nlat, nlevi, dati, psfc, spvl, p0, tbot, phis,&
!                             hbcofa, hbcofb, intyp, kxtrp, varflg, nlevo, plevo, dato)
!
! SUBROUTINE ng_band_pass_area_time  (nlon, nlat, ntim, x, xmsg, spd, bpf,&
!                                     wy, xts, opt_detrend, opt_Nrun)
! SUBROUTINE ng_band_pass_hovmueller (nlon, nlat, ntim, x, xmsg, spd, bpf,&
!                                     wy, xts, opt_detrend)
! SUBROUTINE ng_band_pass_latlon_time(nlon, nlat, ntim, x, xmsg, spd, bpf,&
!                                     xts, opt_detrend, opt_fft, opt_taper)
!
! SUBROUTINE ng_mjo_xcor_lag_season(ntim, npts, ref, x, xmsg, mxlag, ccr,&
!                                   opt_smth9)
! SUBROUTINE ng_mjo_xcor_lag(ntim, npts, date, ref, x, xmsg, seaName,&
!                            mxlag, ccr, opt_smth9)
! SUBROUTINE ng_mjo_wavenum_freq_season(nlon, ntim, x, xmsg, date, seaName, nday,&
!                                       spectra, opt_freq, opt_wave, opt_smth9)
! SUBROUTINE ng_mjo_spectra_season(nlon, nlat, ntim, x, xmsg, wy, date, seaName, nday,&
!                   smjo, smjo_spcx, smjo_frq, smjo_bw, smjo_xvari, smjo_xlag1,&
!                   opt_detrend, opt_detrend_seg, opt_smooth_seg, opt_taper_seg)
! SUBROUTINE ng_mjo_cross(nlon, nlat, ntim, x, y, xmsg, ymsg, segLen,&
!                         segOverLap, stc, stc_freq, stc_wave, stc_dof,&
!                         stc_prob, stc_prob_coh2, stc_segmentLength,&
!                         stc_segmentOverLap, stc_segmentRepeat)
!
! ~~~~~~~~~~~~~~~~~~~~~~~
! Earth Science - Drought
! ~~~~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_spi(ntim, p, pmsg, nrun, spi)
!
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Earth Science - Meteorology
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_zonal_mpsi(nlon, nlat, nlev, lat, p, PS, V, msg, ZM_MPSI)
!
! SUBROUTINE ng_pot_vort_isobaric(nlon, nlat, nlev, p, u, v, t, ylat, grid, pv,&
!                                 s, theta, dthdp, dudp, dvdp, dtdx, dtdy)
!
! SUBROUTINE ng_pot_vort_hybrid  (nlon, nlat, nlev, p, u, v, t, ylat, grid, pv,&
!                                 s, theta, dthdp, dudp, dvdp, dthdx, dthdy)
!
! ELEMENTAL REAL FUNCTION ng_pot_temp(p, t)
!
! SUBROUTINE ng_static_stability(n, p, t, s, theta, dthdp)
!
! SUBROUTINE ng_grad_latlon_cfd(nlon, nlat, xlon, ylat, z, zmsg, cyclic, dzdx, dzdy)
!
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
! Earth Science - Oceanography
! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!
! FUNCTION ng_rho_mwjf(nx, ny, t2d, s2d, spv, depth) RESULT(rho)
!
! ~~~~~~~~~~~~~~~~~~~
! Earth Science - WRF
! ~~~~~~~~~~~~~~~~~~~
!
! SUBROUTINE ng_wrf_dbz(nlon, nlat, nlev, p, t, qv, qr, qs, qg, ivarint, iliqskin, DBZ)
!
! ~~~~~~
! others
! ~~~~~~
!
! FUNCTION ng_fspan( start, finish, npts )
!
! SUBROUTINE SUBROUTINE ng_nice_mnmxintvl( cmin, cmax, max_steps, outside, cmn, cmx, cis, ncl, clev, clab )
!
! SUBROUTINE ng_nice_label1( cmn, cmx, cis, nfl, clab, ncl, clev )
! SUBROUTINE ng_nice_label2( ncl, clev, nfl, clab )
!
! SUBROUTINE ng_convexhull_2d(x, y, n, vertex, nvert)
!
! SUBROUTINE ng_span_two_named_colors(namedcolor1, namedcolor2, ncolors, rgb)
! SUBROUTINE ng_span_named_colors(n_named, named_colors, rgb, ncolors, NumColorsInTable, NumColorsInRange)
!
! SUBROUTINE ng_eemd   ( n, x, nrep, noise, nimf, y, S_number, num_siftings, rng_seed ) for NAG/GNU/G95 only
! SUBROUTINE ng_ceemdan( n, x, nrep, noise, nimf, y, S_number, num_siftings, rng_seed ) for NAG/GNU/G95 only
!
!=====================================================================
! Plots - Wind Rose
!=====================================================================
!
! SUBROUTINE ng_WindRose( vp, nWinds, wspd, wdir, nPetals, circFr, nBounds, spdBounds, clrBounds )
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_WindRose( vp, nWinds, wspd, wdir, nPetals, circFr,&
!                         nBounds, spdBounds, clrBounds )
!
!   REAL,    INTENT(IN) :: vp(4)
!   INTEGER, INTENT(IN) :: nWinds
!   REAL,    INTENT(IN) :: wspd(nWinds), wdir(nWinds)
!   INTEGER, INTENT(IN) :: nPetals
!   REAL,    INTENT(IN) :: circFr
!   INTEGER, INTENT(IN), OPTIONAL :: nBounds
!   REAL,    INTENT(IN), OPTIONAL :: spdBounds(*) ! spdBounds(nBounds)
!   INTEGER, INTENT(IN), OPTIONAL :: clrBounds(*) ! clrBounds(nBounds)
!
! Routine to plot a Wind Rose [ie, frequency of wind direction + avg spd]
!
! Variables:
!
!   vp        - Viewport of plot (in fractional coordinates)
!               in (xmin, xmax, ymin, ymax) order
!
!   nWinds    - Size of wspd and wdir arrays
!
!   wspd      - Wind speed (any units)
!
!   wdir      - Wind direction (degrees)
!               meteorological: dir from which the wind blows
!               eg: 90 deg means blowing from the east
!
!   nPetals   - Number wind wind rose directions (ie., Number of petals)
!               eg: nPetals=8 is common
!               It is best to set "nPetals" to a number like 8 or 16.
!
!   circFr    - Intervals at which frequency circles are drawn
!               eg: circFr=10.0 is common
!
!   nBounds   - Size of spdBounds/clrBounds arrays
!
!   spdBounds - Speed bounds for different line thicknesses (and colors)
!
!   clrBounds - Color indices for each spdBounds interval
!
! Note: "nBounds" should be present, if "spdBounds" present
!       "nBounds" and "spdBounds should be present, if "clrBounds" present
!
!=====================================================================
! Plots - Pie Charts
!=====================================================================
!
! SUBROUTINE ng_pie_chart( vp, nsections, percent, cname, icolor,&
!                          opt_label     ,&
!                          opt_label_mkid,&
!                          opt_label_htsc,&
!                          opt_title     ,&
!                          opt_title_htsc,&
!                          opt_title_yoff )
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_pie_chart( vp, nsections, percent, cname, icolor,&
!                          opt_label     ,&
!                          opt_label_mkid,&
!                          opt_label_htsc,&
!                          opt_title     ,&
!                          opt_title_htsc,&
!                          opt_title_yoff )
!
!   REAL,         INTENT(IN) :: vp(4)
!   INTEGER,      INTENT(IN) :: nsections
!   REAL,         INTENT(IN) :: percent(nsections)
!   CHARACTER(*), INTENT(IN) :: cname  (nsections)
!   INTEGER,      INTENT(IN) :: icolor (nsections)
!   CHARACTER(*), INTENT(IN), OPTIONAL :: opt_label
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_label_mkid
!   REAL,         INTENT(IN), OPTIONAL :: opt_label_htsc
!   CHARACTER(*), INTENT(IN), OPTIONAL :: opt_title
!   REAL,         INTENT(IN), OPTIONAL :: opt_title_htsc
!   REAL,         INTENT(IN), OPTIONAL :: opt_title_yoff
!
! Routine to create a basic Pie Chart. The percent is partitioned over 360
! degrees. The sections proceed in a counter clockwise direction. Some
! labeling options are provided.
!
! Variables:
!
!   vp        - plot viewport
!
!   nsections - number of sections
!
!   percent   - percent [%: 0-100] for each section: SUM(percent)=100
!
!   cname     - names to be associated with each section
!
!   icolor    - color indices for each section
!
!---------
!
!   opt_label      - label type, "section" (default) or "block"
!
!   opt_label_mkid - marker index (default=16; color filled circle)
!
!   opt_label_htsc - scaling factor for size of label/marker (default=1.0)
!
!   opt_title      - string for general title (default is no main title)
!
!   opt_title_htsc - scaling factor for size of title
!
!   opt_title_yoff - scaling factor for size between title/circle
!
!=====================================================================
! Plots - wkSpaceTime
!=====================================================================
!
! SUBROUTINE ng_wkSpaceTime( nlon, nlat, ntim, x, xmsg, spd, nDayWin, nDaySkip,&
!                            varName, pltName, pltTitle,&
!                            opt_pltTitle_sc,&
!                            opt_output_ps,&
!                            opt_output_gif,&
!                            opt_pltColorMap,&
!                            opt_cnLinesOn,&
!                            opt_Fig_1,&
!                            opt_Fig_2,&
!                            opt_Fig_3a,&
!                            opt_Fig_3b,&
!                            opt_CPGRWS,&
!                            opt_AREDAM,&
!                            opt_ARSCAM )
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_wkSpaceTime( nlon, nlat, ntim, x, xmsg, spd, nDayWin, nDaySkip,&
!                            varName, pltName, pltTitle,&
!                            opt_pltTitle_sc,&
!                            opt_output_ps,&
!                            opt_output_gif,&
!                            opt_pltColorMap,&
!                            opt_cnLinesOn,&
!                            opt_Fig_1,&
!                            opt_Fig_2,&
!                            opt_Fig_3a,&
!                            opt_Fig_3b,&
!                            opt_CPGRWS,&
!                            opt_AREDAM,&
!                            opt_ARSCAM )
!
!   INTEGER,      INTENT(IN) :: nlon, nlat, ntim
!   REAL,         INTENT(IN) :: x(nlon,nlat,ntim), xmsg
!   INTEGER,      INTENT(IN) :: spd, nDayWin, nDaySkip
!   CHARACTER(*), INTENT(IN) :: varName, pltName, pltTitle
!   REAL,         INTENT(IN), OPTIONAL :: opt_pltTitle_sc,&
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_output_ps
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_output_gif
!   CHARACTER(*), INTENT(IN), OPTIONAL :: opt_pltColorMap
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_cnLinesOn
!   REAL,         INTENT(IN), OPTIONAL :: opt_Fig_1 (0:*)
!   REAL,         INTENT(IN), OPTIONAL :: opt_Fig_2 (0:*)
!   REAL,         INTENT(IN), OPTIONAL :: opt_Fig_3a(0:*)
!   REAL,         INTENT(IN), OPTIONAL :: opt_Fig_3b(0:*)
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_CPGRWS
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_AREDAM
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_ARSCAM
!
! Routine to calculate and create Wheeler-Kiladis Space-Time Spectra
! Plots.
!
! Variables:
!
!   nlon     - Size of longitude dimension of variable x
!
!   nlat     - Size of latitude dimension of variable x
!
!   ntim     - Size of time dimension of variable x
!
!   x        - Variable data array
!
!   xmsg     - Missing value of variable x
!
!   spd      - Sampling rate ("samples per day") on the variable x.
!              Typically, spd is one of the following [1,2,4,8,12,24].
!              These correspond to [24,12,6,3,2,1] hour sampling rates.
!
!   nDayWin  - Length of the temporal window in days. Typically,
!              for Wheeler-Kiladis space-time spectra, nDayWin=96.
!
!   nDaySkip - Number of days to skip between temporal windows.
!              A negative value means that overlapping windows will be
!              used. For example, if nDayWin=96 and nDaySkip=-65, then
!              the last 65 days of the previous temporal window will
!              be included in the current temporal window.
!
!   varName  - Name of the variable to be processed
!
!   pltName  - Name of graphics output files
!
!   pltTitle - Title to be placed on plots
!
!-------------------
! Optional arguments
!-------------------
!
! opt_pltTitle_sc - Scaling factor of the size of the string "pltTitle"
!                   Default: 1.0
!
! opt_output_gif  - Whether encode/output graphics to ".gif" file
!                   Default: .FALSE.
!
! opt_output_ps   - Whether encode/output graphics to ".ps" file
!                   Default: .TRUE.
!
! opt_pltColorMap - specify color map to be used.
!                   Default: "amwg_blueyellowred"
!
! opt_cnLinesOn   - specify if contour lines are to be plotted.
!                   If, opt_cnLinesOn=.FALSE., then no contour lines will be drawn.
!                   Default: .TRUE.
!
!---------
! Contour levels
!---------
!
! This routine has contour levels 'hard-wired' for specific variable names [varName]:
! "FLUT", "OLR", "olr", "U200", "U850", "OMEGA500" and "PRECT". If the user wishes to
! override these contour intervals or, if the varName is not one of the hard-wired
! variables, the user may specify the contour levels to be used via the appropriate
! optional arguments: opt_Fig_1, opt_Fig_2, opt_Fig_3a, and/or, opt_Fig_3b. Otherwise,
! this routine will automatically choose contour levels.
!
! opt_Fig_1  - specify the contour levels for "Figure 1" of the Wheeler-Kiladis paper.
!
!              NINT(opt_Fig_1(0))              - number of contour levels
!              opt_Fig_1(1:NINT(opt_Fig_1(0))) - list of contour levels
!
! opt_Fig_2  - specify the contour levels for "Figure 2" of the Wheeler-Kiladis paper
!
! opt_Fig_3a - specify the contour levels for "Figure 3a" of the Wheeler-Kiladis paper
!
! opt_Fig_3b - specify the contour levels for "Figure 3b" of the Wheeler-Kiladis paper
!
! Note:
!
!   It is recommended that 15 contour levels be specified.
!
!     ! equal spacing
!     opt_Fig_1(0:15) = (/15.0, ng_fspan(-3.3,0.9,15)/)
!
!   or
!
!     ! unequal
!     opt_Fig_1(0:15) = (/15.0, -18.2, -18.0, -17.8, -17.6, -17.5, -17.4, -17.3,&
!                        -17.2, -17.1, -17.0, -16.9, -16.8, -16.7, -16.6, -16.5/)
!
!---------
! Size of working arrays
!---------
!
! opt_CPGRWS - specify size of working arrays used for ConPack-CPGRWS
!              Default: 10000
!
!              Add working array size opt_CPGRWS, if run-time warn:
!              "CPGRWS - xxx WORDS REQUESTED, xxx WORDS AVAILABLE"
!
! opt_AREDAM - specify size of working arrays used for AreaMap-AREDAM
!              Default: 1000000
!
!              Add working array size opt_AREDAM, if run-time error:
!              "ERROR 7 IN AREDAM - AREA-MAP ARRAY OVERFLOW"
!
! opt_ARSCAM - specify size of working arrays used for AreaMap-ARSCAM
!              Default: 20000
!
!              Add working array size opt_ARSCAM, if run-time error:
!              "ERROR 8 IN ARSCAM - MCS TOO SMALL"
!
!=====================================================================
! Plots - Taylor Diagram
!=====================================================================
!
! SUBROUTINE ng_taylor_metrics_table( vp, nvar, nseason, ncase, vars,&
!                                     seasons, cases, values, colors,&
!                                     opt_title,&
!                                     opt_bound )
!
! SUBROUTINE ng_taylor_diagram( vp, nvar, ncase, ratio, cc, marker, color,&
!                               opt_sc_mark,&
!                               opt_sc_clab,&
!                               opt_sc_yoff,&
!                               opt_centerDiffRMS, &
!                               opt_centerDiffRMS_color,&
!                               opt_stnRad,&
!                               opt_stnRad_color,&
!                               opt_ccRays,&
!                               opt_ccRays_color,&
!                               opt_caseLabels,&
!                               opt_caseLabels_htsc,&
!                               opt_caseLabels_xloc,&
!                               opt_caseLabels_yloc,&
!                               opt_varLabels,&
!                               opt_varLabels_htsc,&
!                               opt_varLabels_xloc,&
!                               opt_varLabels_yloc,&
!                               opt_tiMainString )
!
! SUBROUTINE ng_taylor_diagram_cam( vp, nvar, ncase, ratio, cc, bias, color,&
!                                   opt_sc_mark,&
!                                   opt_sc_clab,&
!                                   opt_sc_yoff,&
!                                   opt_centerDiffRMS, &
!                                   opt_centerDiffRMS_color,&
!                                   opt_stnRad,&
!                                   opt_stnRad_color,&
!                                   opt_ccRays,&
!                                   opt_ccRays_color,&
!                                   opt_caseLabels,&
!                                   opt_caseLabels_htsc,&
!                                   opt_caseLabels_xloc,&
!                                   opt_caseLabels_yloc,&
!                                   opt_varLabels,&
!                                   opt_varLabels_htsc,&
!                                   opt_varLabels_xloc,&
!                                   opt_varLabels_yloc,&
!                                   opt_biasLabels_htsc,&
!                                   opt_biasLabels_xloc,&
!                                   opt_biasLabels_yloc,&
!                                   opt_tiMainString )
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_taylor_metrics_table( vp, nvar, nseason, ncase, vars,&
!                                     seasons, cases, values, colors,&
!                                     opt_title,&
!                                     opt_bound )
!
!   REAL,         INTENT(IN   ) :: vp(4)
!   INTEGER,      INTENT(IN   ) :: nvar, nseason, ncase
!   CHARACTER(*), INTENT(IN   ) :: vars(nvar), seasons(nseason), cases(ncase)
!   REAL,         INTENT(IN   ) :: values(nvar,nseason,ncase)
!   INTEGER,      INTENT(IN   ) :: colors(5)
!   CHARACTER(*), INTENT(IN   ), OPTIONAL :: opt_title
!   REAL,         INTENT(  OUT), OPTIONAL :: opt_bound(4)
!
! Routine to draw the Taylor Diagram Metrics Table
!
! Variables:
!
!   vp        - viewport of plot, (xmin,xmax,ymin,ymax)
!
!   nvar      - numbewr of variables
!
!   nseason   - number of seasons
!
!   ncase     - number of cases
!
!   vars      - variable names [metrics]
!
!   seasons   - season names
!
!   cases     - case (model) names
!
!   values    - array containing the values to be plotted
!
!   colors    - background colors
!
!               opt_color(1) - for title
!               opt_color(2) - for variable/season/case names
!               opt_color(3) - for reference (1st case) value
!               opt_color(4) - for values <= reference-value
!               opt_color(5) - for values >  reference-value
!
!               NCL suggest: "CornflowerBlue", "Gray70", "White",
!                            "DarkOliveGreen3", and "IndianRed1"
!
!   opt_title - table title
!               default is "CAM METRICS", if argument not present or blank
!
!   opt_bound - bounding coordinates of table, (xmin,xmax,ymin,ymax)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_taylor_diagram( vp, nvar, ncase, ratio, cc, marker, color,&
!                               opt_sc_mark,&
!                               opt_sc_clab,&
!                               opt_sc_yoff,&
!                               opt_centerDiffRMS, &
!                               opt_centerDiffRMS_color,&
!                               opt_stnRad,&
!                               opt_stnRad_color,&
!                               opt_ccRays,&
!                               opt_ccRays_color,&
!                               opt_caseLabels,&
!                               opt_caseLabels_htsc,&
!                               opt_caseLabels_xloc,&
!                               opt_caseLabels_yloc,&
!                               opt_varLabels,&
!                               opt_varLabels_htsc,&
!                               opt_varLabels_xloc,&
!                               opt_varLabels_yloc,&
!                               opt_tiMainString )
!
!   REAL,         INTENT(IN) :: vp(4)
!   INTEGER,      INTENT(IN) :: nvar, ncase
!   REAL,         INTENT(IN) :: ratio(nvar,ncase), cc(nvar,ncase)
!   INTEGER,      INTENT(IN) :: marker(ncase)
!   INTEGER,      INTENT(IN) :: color (ncase)
!   REAL,         INTENT(IN), OPTIONAL :: opt_sc_mark
!   REAL,         INTENT(IN), OPTIONAL :: opt_sc_clab
!   REAL,         INTENT(IN), OPTIONAL :: opt_sc_yoff
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_centerDiffRMS
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_centerDiffRMS_color
!   REAL,         INTENT(IN), OPTIONAL :: opt_stnRad(0:*)
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_stnRad_color
!   REAL,         INTENT(IN), OPTIONAL :: opt_ccRays(0:*)
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_ccRays_color
!   CHARACTER(*), INTENT(IN), OPTIONAL :: opt_caseLabels(nCase)
!   REAL,         INTENT(IN), OPTIONAL :: opt_caseLabels_htsc
!   REAL,         INTENT(IN), OPTIONAL :: opt_caseLabels_xloc
!   REAL,         INTENT(IN), OPTIONAL :: opt_caseLabels_yloc
!   CHARACTER(*), INTENT(IN), OPTIONAL :: opt_varLabels(nVar)
!   REAL,         INTENT(IN), OPTIONAL :: opt_varLabels_htsc
!   REAL,         INTENT(IN), OPTIONAL :: opt_varLabels_xloc
!   REAL,         INTENT(IN), OPTIONAL :: opt_varLabels_yloc
!   CHARACTER(*), INTENT(IN), OPTIONAL :: opt_tiMainString
!
! Routine to generate a Taylor Diagram
!
! Variables:
!
!   vp     - viewport of plot, (xmin,xmax,ymin,ymax)
!
!   nvar   - number of variables (points)
!
!   ncase  - number of cases (models, datasets)
!
!   ratio  - ratio of the standardized variances
!
!   cc     - pattern (cross) correlations, range 0-to-1
!
!   marker - Marker styles (indices)
!            NCL suggest: 4, 6, 8, 0, 9, 12, 7, 2, 11, 16
!
!   color  - Color indices of marker
!            NCL suggest: red, blue, green, cyan, orange, turquoise,
!                         brown, yellow, purple, black
!
!---------
!
!   opt_sc_mark - Scaling factor of marker size               (default: 1.0)
!   opt_sc_clab - Scaling factor of marker-label height       (default: 1.0)
!   opt_sc_yoff - Scaling factor of size between marker/label (default: 1.0)
!
!   opt_centerDiffRMS       - RMS 'circles'                (default: .FALSE.)
!   opt_centerDiffRMS_color - Color index of RMS 'circles' (defailt: 1      )
!
!   opt_stnRad(0:*)  - Additional standard radii
!                        NINT(opt_stnRad(0)) - number of radii (n)
!                        opt_stnRad(1:n)     - list of radii
!   opt_stnRad_color - Color index of additional standard radii,(default: 1)
!
!   opt_ccRays(0:*)  - Correlation rays
!                        NINT(opt_ccRays(0)) - number of rays (n)
!                        opt_ccRays(1:n)     - list of rays
!   opt_ccRays_color - Color index of correlation rays,(default: 1)
!
!   opt_caseLabels      - Case labels
!   opt_caseLabels_htsc - Scaling factor of case labels height (default: 1.0)
!   opt_caseLabels_xloc - X-location (left)   of case labels   (default: 1.4)
!   opt_caseLabels_yloc - Y-location (bottom) of case labels   (default: 1.4)
!
!   opt_varLabels       - Variable labels
!   opt_varLabels_htsc  - Scaling factor of variable labels height (default: 1.0 )
!   opt_varLabels_xloc  - X-location (left)   of variable labels   (default: 0.05)
!   opt_varLabels_yloc  - Y-location (bottom) of variable labels   (default: 0.05)
!
!   opt_tiMainString - Title of plot
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_taylor_diagram_cam( vp, nvar, ncase, ratio, cc, bias, color,&
!                                   opt_sc_mark,&
!                                   opt_sc_clab,&
!                                   opt_sc_yoff,&
!                                   opt_centerDiffRMS, &
!                                   opt_centerDiffRMS_color,&
!                                   opt_stnRad,&
!                                   opt_stnRad_color,&
!                                   opt_ccRays,&
!                                   opt_ccRays_color,&
!                                   opt_caseLabels,&
!                                   opt_caseLabels_htsc,&
!                                   opt_caseLabels_xloc,&
!                                   opt_caseLabels_yloc,&
!                                   opt_varLabels,&
!                                   opt_varLabels_htsc,&
!                                   opt_varLabels_xloc,&
!                                   opt_varLabels_yloc,&
!                                   opt_biasLabels_htsc,&
!                                   opt_biasLabels_xloc,&
!                                   opt_biasLabels_yloc,&
!                                   opt_tiMainString )
!
!   REAL,         INTENT(IN) :: vp(4)
!   INTEGER,      INTENT(IN) :: nvar, ncase
!   REAL,         INTENT(IN) :: ratio(nvar,ncase), cc(nvar,ncase), bias(nvar,ncase)
!   INTEGER,      INTENT(IN) :: color (ncase)
!   REAL,         INTENT(IN), OPTIONAL :: opt_sc_mark
!   REAL,         INTENT(IN), OPTIONAL :: opt_sc_clab
!   REAL,         INTENT(IN), OPTIONAL :: opt_sc_yoff
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_centerDiffRMS
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_centerDiffRMS_color
!   REAL,         INTENT(IN), OPTIONAL :: opt_stnRad(0:*)
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_stnRad_color
!   REAL,         INTENT(IN), OPTIONAL :: opt_ccRays(0:*)
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_ccRays_color
!   CHARACTER(*), INTENT(IN), OPTIONAL :: opt_caseLabels(nCase)
!   REAL,         INTENT(IN), OPTIONAL :: opt_caseLabels_htsc
!   REAL,         INTENT(IN), OPTIONAL :: opt_caseLabels_xloc
!   REAL,         INTENT(IN), OPTIONAL :: opt_caseLabels_yloc
!   CHARACTER(*), INTENT(IN), OPTIONAL :: opt_varLabels(nVar)
!   REAL,         INTENT(IN), OPTIONAL :: opt_varLabels_htsc
!   REAL,         INTENT(IN), OPTIONAL :: opt_varLabels_xloc
!   REAL,         INTENT(IN), OPTIONAL :: opt_varLabels_yloc
!   REAL,         INTENT(IN), OPTIONAL :: opt_biasLabels_htsc
!   REAL,         INTENT(IN), OPTIONAL :: opt_biasLabels_xloc
!   REAL,         INTENT(IN), OPTIONAL :: opt_biasLabels_yloc
!   CHARACTER(*), INTENT(IN), OPTIONAL :: opt_tiMainString
!
! Routine to generate a Taylor Diagram. This "cam" version routine
! plot the percent bias of each case for each variable. Further,
! it plots negative correlations and standard deviations > 1.65 as
! text at the bottom of the figure.
!
! Variables:
!
!   vp     - viewport of plot, (xmin,xmax,ymin,ymax)
!
!   nvar   - number of variables (points)
!
!   ncase  - number of cases (models, datasets)
!
!   ratio  - ratio of the standardized variances
!
!   cc     - pattern (cross) correlations, range 0-to-1
!
!   bias   - rlative bias (%)
!
!   color  - Color indices of marker
!
!---------
!
!   opt_sc_mark - Scaling factor of marker size               (default: 1.0)
!   opt_sc_clab - Scaling factor of marker-label height       (default: 1.0)
!   opt_sc_yoff - Scaling factor of size between marker/label (default: 1.0)
!
!   opt_centerDiffRMS       - RMS 'circles'                (default: .FALSE.)
!   opt_centerDiffRMS_color - Color index of RMS 'circles' (defailt: 1      )
!
!   opt_stnRad(0:*)  - Additional standard radii
!                        NINT(opt_stnRad(0)) - number of radii (n)
!                        opt_stnRad(1:n)     - list of radii
!   opt_stnRad_color - Color index of additional standard radii,(default: 1)
!
!   opt_ccRays(0:*)  - Correlation rays
!                        NINT(opt_ccRays(0)) - number of rays (n)
!                        opt_ccRays(1:n)     - list of rays
!   opt_ccRays_color - Color index of correlation rays,(default: 1)
!
!   opt_caseLabels      - Case labels
!   opt_caseLabels_htsc - Scaling factor of case labels height (default: 1.0)
!   opt_caseLabels_xloc - X-location (left)   of case labels   (default: 1.4)
!   opt_caseLabels_yloc - Y-location (bottom) of case labels   (default: 1.4)
!
!   opt_varLabels       - Variable labels
!   opt_varLabels_htsc  - Scaling factor of variable labels height (default: 1.0 )
!   opt_varLabels_xloc  - X-location (left)   of variable labels   (default: 0.05)
!   opt_varLabels_yloc  - Y-location (bottom) of variable labels   (default: 0.05)
!
!   opt_biasLabels_htsc - Scaling factor of bias labels height (default: 1.0 )
!   opt_biasLabels_xloc - X-location (left) of bias labels     (default: 0.05)
!   opt_biasLabels_yloc - Y-location (top)  of bias labels     (default: 1.55)
!
!   opt_tiMainString - Title of plot
!
!
!=====================================================================
! Plots - Skew-T
!=====================================================================
!
! SUBROUTINE ng_skewT_BackGround( vp, bkcolor,&
!                                 opt_DrawColAreaFill   ,&
!                                 opt_DrawColLine       ,&
!                                 opt_DrawIsotherm      ,&
!                                 opt_DrawIsobar        ,&
!                                 opt_DrawMixRatio      ,&
!                                 opt_DrawDryAdiabat    ,&
!                                 opt_DrawMoistAdiabat  ,&
!                                 opt_DrawStandardAtm   ,&
!                                 opt_DrawStandardAtmThk,&
!                                 opt_DrawWind          ,&
!                                 opt_DrawHeightScale   ,&
!                                 opt_DrawHeightScaleFt ,&
!                                 opt_DrawFahrenheit    ,&
!                                 opt_tiMainString       )
!
! SUBROUTINE ng_skewT_PlotData( n, p, tc, tdc, z, wspd, wdir, spv, color, lwsc, dash,&
!                               opt_ThermoInfo     ,&
!                               opt_Parcel         ,&
!                               opt_Cape           ,&
!                               opt_PrintZ         ,&
!                               opt_PlotWindP      ,&
!                               opt_hemisphere     ,&
!                               opt_WspdWdir       ,&
!                               opt_Wthin          ,&
!                               opt_xpWind         ,&
!                               opt_PlotWindH      ,&
!                               opt_Height         ,&
!                               opt_Hspd           ,&
!                               opt_Hdir           ,&
!                               opt_HspdHdir        )
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_skewT_BackGround( vp, bkcolor,&
!                                 opt_DrawColAreaFill   ,&
!                                 opt_DrawColLine       ,&
!                                 opt_DrawIsotherm      ,&
!                                 opt_DrawIsobar        ,&
!                                 opt_DrawMixRatio      ,&
!                                 opt_DrawDryAdiabat    ,&
!                                 opt_DrawMoistAdiabat  ,&
!                                 opt_DrawStandardAtm   ,&
!                                 opt_DrawStandardAtmThk,&
!                                 opt_DrawWind          ,&
!                                 opt_DrawHeightScale   ,&
!                                 opt_DrawHeightScaleFt ,&
!                                 opt_DrawFahrenheit    ,&
!                                 opt_tiMainString      )
!
!   REAL,         INTENT(IN) :: vp(4)
!   INTEGER,      INTENT(IN) :: bkcolor(4)
!
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_DrawColAreaFill
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_DrawColLine
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_DrawIsotherm
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_DrawIsobar
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_DrawMixRatio
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_DrawDryAdiabat
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_DrawMoistAdiabat
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_DrawStandardAtm
!   REAL,         INTENT(IN), OPTIONAL :: opt_DrawStandardAtmThk
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_DrawWind
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_DrawHeightScale
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_DrawHeightScaleFt
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_DrawFahrenheit
!   CHARACTER(*), INTENT(IN), OPTIONAL :: opt_tiMainString
!
! Routine to create a background chart for Skew T, Log P plotting.
! The primary use of this routine is to create a background for use
! with subroutine ng_skewT_PlotData.
!
! Variables:
!
! vp      - Viewport of plot
!
! bkcolor - Color indices for drawing graphics objects
!
!           bkcolor(1) - Color index for ColArea Fill (fill-1)
!                        NCL suggest: 'LightGreen' or 'PaleGreen'
!
!           bkcolor(2) - Color index for ColArea Fill (fill-2)
!                        NCL suggest: 'White' (background color)
!
!           bkcolor(3) - Color index for draw Mix Ratio and Moist Adiabat (line/text)
!                        NCL suggest: 'Green'
!
!           bkcolor(4) - Color index for draw Isotherm, Isobar,
!                        Dry Adiabat, and Standard Atm (line/text)
!                        NCL suggest: 'Tan' or 'Gray'
!
!---------
! Optional
!---------
!                          Default  Description
!
! opt_DrawColAreaFill    - .FALSE.  Color Fill Area of plot, colors defined by argument "bkcolor"
!
! opt_DrawColLine        - .TRUE.   Colorful (.TRUE., bkcolor) or mono (.FALSE., foreground) polylines
!
! opt_DrawIsotherm       - .TRUE.   Draw diagonal isotherms
!
! opt_DrawIsobar         - .TRUE.   Draw horizontal isobars
!
! opt_DrawMixRatio       - .TRUE.   Draw saturation mixing ratio lines
!
! opt_DrawDryAdiabat     - .TRUE.   Draw dry adiabats
!
! opt_DrawMoistAdiabat   - .TRUE.   Draw moist adiabats
!
! opt_DrawStandardAtm    - .TRUE.   Draw standard atm
!
! opt_DrawStandardAtmThk - 2.0      Line width scaling factor for draw standard atm
!
! opt_DrawWind           - .TRUE.   Draw vertical line upon which to plot wind barbs
!
! opt_DrawHeightScale    - .FALSE.  Draw Height Scale Axis
!
! opt_DrawHeightScaleFt  - .TRUE.   "Feet" (.TRUE.) or "Km" (.FALSE.) unit of "Height"
!
! opt_DrawFahrenheit     - .TRUE.   "Fahrenheit" (.TRUE.) or "Celsius" (.FALSE.) unit of "Termperature"
!
! opt_tiMainString       - " "      User specified main Title
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_skewT_PlotData( n, p, tc, tdc, z, wspd, wdir, spv, color, lwsc, dash,&
!
!                               opt_ThermoInfo     ,&
!                               opt_Parcel         ,&
!
!                               opt_Cape           ,&
!
!                               opt_PrintZ         ,&
!
!                               opt_PlotWindP      ,&
!                               opt_hemisphere     ,&
!                               opt_WspdWdir       ,&
!                               opt_Wthin          ,&
!                               opt_xpWind         ,&
!
!                               opt_PlotWindH      ,&
!                               opt_Height         ,&
!                               opt_Hspd           ,&
!                               opt_Hdir           ,&
!                               opt_HspdHdir )
!
!   INTEGER,       INTENT(IN) :: n
!   REAL,          INTENT(IN) :: p(n), tc(n), tdc(n), z(n), wspd(n), wdir(n)
!   REAL,          INTENT(IN) :: spv(6)
!   INTEGER,       INTENT(IN) :: color(8)
!   REAL,          INTENT(IN) :: lwsc (8)
!   INTEGER,       INTENT(IN) :: dash (3)
!
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_ThermoInfo
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_Parcel
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_Cape
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_PrintZ
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_PlotWindP
!   CHARACTER(*), INTENT(IN), OPTIONAL :: opt_hemisphere
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_WspdWdir
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_Wthin
!   REAL,         INTENT(IN), OPTIONAL :: opt_xpWind
!   INTEGER,      INTENT(IN), OPTIONAL :: opt_PlotWindH
!   REAL,         INTENT(IN), OPTIONAL :: opt_Height(*)
!   REAL,         INTENT(IN), OPTIONAL :: opt_Hspd  (*)
!   REAL,         INTENT(IN), OPTIONAL :: opt_Hdir  (*)
!   LOGICAL,      INTENT(IN), OPTIONAL :: opt_HspdHdir
!
! Routine to plot a sounding and (optionally) winds on Skew T,
! Log P charts created by ng_skewT_BackGround.
!
! Variables:
!
!   n    - Size of arrays p, tc,tdc, z, wspd, and, wdir
!
!   p    - Pressure values (mb/hPa).
!
!   tc   - Temperature values.
!          By default these are assumed to be in Fahrenheit.
!          If you are using Celsius, then you need to specify
!          this by setting opt_DrawFahrenheit to .FALSE..
!
!   tdc  - Dew point temperature values.
!          By default these are assumed to be in Fahrenheit.
!          If you are using Celsius, then you need to specify
!          this by setting opt_DrawFahrenheit to False.
!
!   z    - Geopotential values (gpm).
!
!   wspd - Wind speeds (knots or m/s) or wind u-components.
!
!   wdir - Meteorological wind directions or wind v-components.
!
!   spv  - Missing values
!          spv(1) : Missing value of p
!          spv(2) : Missing value of tc
!          spv(3) : Missing value of tdc
!          spv(4) : Missing value of z
!          spv(5) : Missing value of wspd
!          spv(6) : Missing value of wdir
!
!   If wind speeds and directions are supplied in arguments wspd and
!   wdir at places where pressures are missing, then, if geopotential
!   values exist at those locations where pressures are missing the
!   geopotential values are mapped (interpolated to) pressure values
!   and the wind barbs are drawn at those pressures.
!
!---------
!
!   This routine draw following 8 graphucs objects
!
!     [1] Plot [Temperature ~ Pressure Profile]
!
!     [2] Plot [Dew point temperature ~ Pressure Profile]
!
!     [3] Plot [CAPE Parcel Profile]
!
!     [4] Plot [Wind Barbs at P levels (where "P/Wind" are not missing)]
!
!     [5] Plot [Wind Barbs at P levels (where "P" is missing, "Z/Wind" are normal)]
!
!     [6] Plot [Wind Barbs at H levels]
!
!     [7] Plot [Thermodynamic Info Text]
!
!     [8] Plot [Geopotential Z Labels]
!
!   having "color", "lwsc", and "dash" graphics attribute arguments
!
!     color - Color indices for drawing:
!
!             color(1) - [Temperature ~ Pressure Profile]
!                        NCL attribute/suggest: colTemperature/"Black"
!
!             color(2) - [Dew point temperature ~ Pressure Profile]
!                        NCL attribute/suggest: colDewPt/"RoyalBlue"
!
!             color(3) - [CAPE Parcel Profile]
!                        NCL attribute/suggest: colCape/"Red"
!
!             color(4) - [Wind Barbs at P levels (where "P/Wind" are not missing)]
!                        NCL attribute/suggest: colWindP/same as icolor(1)
!
!             color(5) - [Wind Barbs at P levels (where "P" is missing, "Z/Wind" are normal)]
!                        NCL attribute/suggest: colWindZ/same as icolor(1)
!
!             color(6) - [Wind Barbs at H levels]
!                        NCL attribute/suggest: colWindH/same as icolor(1)
!
!             color(7) - [Thermodynamic Info Text]
!                        NCL attribute/suggest: colThermoInf/"Sienna"
!
!             color(8) - [Geopotential Z Labels]
!                        NCL attribute/suggest: colZLabel/same as icolor(1)
!
!     lwsc  - "Scaling factor" of "line width" or "text height" for drawing:
!
!             lwsc(1) - [Temperature ~ Pressure Profile]
!
!             lwsc(2) - [Dew point temperature ~ Pressure Profile]
!
!             lwsc(3) - [CAPE Parcel Profile]
!
!             lwsc(4) - [Wind Barbs at P levels (where "P/Wind" are not missing)]
!
!             lwsc(5) - [Wind Barbs at P levels (where "P" is missing, "Z/Wind" are normal)]
!
!             lwsc(6) - [Wind Barbs at H levels]
!
!             lwsc(7) - [Thermodynamic Info Text], text height scaling factor
!
!             lwsc(8) - [Geopotential Z Label], text height scaling factor
!
!     dash  - dash line pattern for drawing:
!
!             dash(1) - [Temperature ~ Pressure Profile]
!
!             dash(2) - [Dew point temperature ~ Pressure Profile]
!
!             dash(3) - [CAPE Parcel Profile]
!
!---------
! Optional
!---------
!
! opt_ThermoInfo       .TRUE.  Print thermodynamic info
! opt_Parcel            1      Subscript corresponding to initial parcel
!
! opt_Cape             .TRUE.  Plot CAPE parcel profile if cape>0
!
! opt_PrintZ           .TRUE.  Print geopotential (Z) on skewT diagram
!
! opt_PlotWindP        .TRUE.  Plot wind barbs at p lvls
! opt_hemisphere        "NH"   Hemisphere wind barbs (NH or SH)
! opt_WspdWdir         .TRUE.  Arguments wspd/wdir are "speed/dir" (.TRUE.) or "u/v components" (.FALSE.)
! opt_Wthin             2      Plot every "opt_Wthin"th wind barb
! opt_xpWind            45.0   x location of wind barb
!
! opt_PlotWindH         0      Number of wind barbs at h lvls to be plotted (<=0 means none)
! opt_Height                   Height of wind reports, missing values not allowed
! opt_Hspd                     Speed [or u component], missing values not allowed
! opt_Hdir                     Dir   [or v component], missing values not allowed
! opt_HspdHdir         .TRUE.  opt_Hspd/opt_Hdir are "speed/dir" (.TRUE.) or "u/v components" (.FALSE.)
!
!=====================================================================
! Plots - Evans
!=====================================================================
!
! SUBROUTINE ng_evans_plotdata( n, hue_data, sat_data, spv, nhue, nsat,&
!                               hue_levels, sat_levels, var_plot )
!
! SUBROUTINE ng_evans_colormap( nhue, nsat, ColorMap,&
!                               opt_NumMaxSat,&
!                               opt_SatMin   ,&
!                               opt_ValMin   ,&
!                               opt_HueOffset,&
!                               opt_HueCyclic,&
!                               opt_RevHue   ,&
!                               opt_RevSat    )
!
! SUBROUTINE ng_evans_labelbar( vl, vr, vb, vt, nhue, nsat, cmap,&
!                               hue_labels, sat_minmax,&
!                               opt_hue_units,&
!                               opt_sat_units,&
!                               opt_hsfb     ,&
!                               opt_wsfb     ,&
!                               opt_htsc      )
!
! SUBROUTINE ng_evans_colorwheel( cx, cy, cs, nhue, nsat, cmap,&
!                                 hue_labels, sat_minmax,&
!                                 opt_title,&
!                                 opt_htsc  )
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_evans_plotdata( n, hue_data, sat_data, spv, nhue, nsat,&
!                               hue_levels, sat_levels, var_plot )
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: hue_data(n), sat_data(n), spv
!   INTEGER, INTENT(IN   ) :: nhue, nsat
!   REAL,    INTENT(IN   ) :: hue_levels(nhue-1), sat_levels(nsat-1)
!   REAL,    INTENT(  OUT) :: var_plot(n)
!
! Routine to create plotting data to use in an Evans plot.
!
! A Hue/Saturation(intensity) plot (or Evans plot for short) is a way
! to visualize spatially, two variables of interest, one of which
! provides some measure of "importance". It is also able to visualize,
! in a natural way, a cyclic variable (such as time of day, time of
! year, etc). It does this by assigning the hue of a color to one
! variable (which may be cyclic) and the saturation of color to the
! other variable. The variable associated with saturation indicates
! "importance" since low values of this variable fade into grey
! regardless of the value of the variable associated with the hue.
!
! The template and examples for this series of plots were written by
! Dr. Jason Evans, an ARC Australian Research Fellow at the Climate
! Change Research Center, University of New South Wales, Sydney,
! Australia.
!
! Variables:
!
!   n          - Size of data
!
!   hue_data   - Dtaa of hue variable, to be mapped as color
!
!   sat_data   - Data of saturation variable to be mapped as intensity
!
!   spv        - Missing value of hue_data and sat_data
!
!   nhue       - Number of hues (colors)
!
!   nsat       - Number of sats (intensities)
!
!   hue_levels - List of hue levels (size of nhue-1)
!
!   sat_levels - List of sat levels (size of nsat-1)
!
!   var_plot   - Data created to use in an Evans plot
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_evans_colormap( nhue, nsat, ColorMap,&
!                               opt_HueCyclic,&
!                               opt_NumMaxSat,&
!                               opt_SatMin   ,&
!                               opt_ValMin   ,&
!                               opt_HueOffset,&
!                               opt_RevHue   ,&
!                               opt_RevSat    )
!
!   INTEGER, INTENT(IN   ) :: nhue, nsat
!   REAL,    INTENT(  OUT) :: ColorMap(3,nsat*nhue) !---> ColorMap(3,nsat,nhue)
!   LOGICAL, INTENT(IN   ), OPTIONAL :: opt_HueCyclic
!   INTEGER, INTENT(IN   ), OPTIONAL :: opt_NumMaxSat
!   REAL,    INTENT(IN   ), OPTIONAL :: opt_SatMin, opt_ValMin, opt_HueOffset
!   LOGICAL, INTENT(IN   ), OPTIONAL :: opt_RevHue, opt_RevSat
!
! Routine to create RGB colormap to use with an Evans plot.
!
! Variables:
!
!   nhue      - Number of hue colors
!
!   nsat      - Number of saturations (intensities)
!
!   ColorMap  - RGB colors converted from HSV color space
!
!---------
!
!   opt_NumMaxSat - Number of saturation levels to be fully saturated and
!                   distinguished by changes in intensity
!                   NCL default: [1 if <6 sat levels (nSat<6), 4 otherwise]
!
!   opt_SatMin    - Minimum saturation to use (0-1)
!                   NCL default: [0.0]
!
!   opt_ValMin    - Minimum intensity  to use (0-1)
!                   NCL default: [0.8]
!
!   opt_HueOffset - Make the first hue this many degrees around the color wheel from red (0-360)
!                   NCL default: [0.0]
!
!   opt_HueCyclic - Is the hue variable cyclic?
!                   NCL default: [.TRUE.]
!
!   opt_RevHue    - Reverse the order of the Hues?
!                   NCL default: [.FALSE.]
!
!   opt_RevSat    - Reverse the order of the Saturation/Intensity changes?
!                   NCL default: [.FALSE.]
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_evans_labelbar( vl, vr, vb, vt, nhue, nsat, cmap,&
!                               hue_labels, sat_minmax,&
!                               opt_hue_units,&
!                               opt_sat_units,&
!                               opt_hsfb     ,&
!                               opt_wsfb     ,&
!                               opt_htsc      )
!
!   REAL,         INTENT(IN) :: vl, vr, vb, vt
!   INTEGER,      INTENT(IN) :: nhue, nsat
!   INTEGER,      INTENT(IN) :: cmap(nsat,nhue) !---> cmap(nsat*nhue)
!   CHARACTER(*), INTENT(IN) :: hue_labels(nhue-1), sat_minmax(2)
!   CHARACTER(*), INTENT(IN) :: hue_units, sat_units
!   REAL,         INTENT(IN), OPTIONAL :: opt_hsfb, opt_wsfb, opt_htsc
!
! Routine to draw a horizontal label bar to use with an Evans plot.
! It also adds labels for the colors and a magnitude vector for the
! saturation values.
!
! Variables:
!
!   vl, vr,    - Viewport of label bar plot
!   vb, vt       left/ight/bottom/top coordinates, in ndc
!
!   nhue       - Number of hue colors
!
!   nsat       - Number of saturations (intensities)
!
!   cmap       - Color indices of RGB colormap
!
!   hue_labels - Labels of hue levels
!
!   sat_minmax - Labels of min/max saturation levels
!
!---------
!
!   opt_hue_units - Hue unit label
!
!   opt_sat_units - Sat unit label
!
!   opt_hsfb      - Fraction of viewport height used for color bar
!                   NCL suggest: 0.5
!
!   opt_wsfb      - Fraction of viewport width  used for color bar
!                   NCL suggest: 0.8
!
!   opt_htsc      - Scaling factor of character size (height)
!                   NCL suggest: 1.0
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_evans_colorwheel( cx, cy, cs, nhue, nsat, cmap,&
!                                 hue_labels, sat_minmax,&
!                                 opt_title,&
!                                 opt_htsc  )
!
!   REAL,         INTENT(IN) :: cx, cy, cs
!   INTEGER,      INTENT(IN) :: nhue, nsat
!   INTEGER,      INTENT(IN) :: cmap(nsat,nhue) !---> cmap(nsat*nhue)
!   CHARACTER(*), INTENT(IN) :: hue_labels(nhue), sat_minmax(2)
!   CHARACTER(*), INTENT(IN), OPTIONAL :: opt_title
!   REAL,         INTENT(IN), OPTIONAL :: opt_htsc
!
! Routine to draw an actual color wheel to use with an Evans plot.
! It also adds labels for the colors and a magnitude vector for the
! saturation values.
!
! Variables:
!
!   cx         - Center X of color wheel in ndc
!
!   cy         - Center Y of color wheel in ndc
!
!   cs         - Size of color wheel in ndc
!
!   nhue       - Number of hue colors
!
!   nsat       - Number of saturations (intensities)
!
!   cmap       - Color indices of RGB colormap
!
!   hue_labels - Labels of hue levels
!
!   sat_minmax - Labels of min/max saturations
!
!   opt_title  - Buttom title of plot
!
!   opt_htsc   - Scaling factor of character size (height)
!                NCL suggest: 1.0
!
!=====================================================================
! CPMPXY3 - 2D Coordinates Mapping
!=====================================================================
!
! SUBROUTINE NG_CPMPXY3_INIT(X2D, Y2D, NX, NY)
! SUBROUTINE NG_CPMPXY3(IMAP, XINP, YINP, XOUT, YOUT)
! SUBROUTINE NG_CPMPXY3_FREE()
!
! SUBROUTINE NG_CPMPXY3MAP_INIT(XLON, YLAT, NLON, NLAT)
! SUBROUTINE NG_CPMPXY3MAP(IMAP, XINP, YINP, XOUT, YOUT)
! SUBROUTINE NG_CPMPXY3MAP_FREE()
!
!---------------------------------------------------------------------
! CPMPXY3 - 2D x/y
!---------------------------------------------------------------------
!
! SUBROUTINE NG_CPMPXY3_INIT( X2D, Y2D, NX, NY )
!
!   INTEGER, INTENT(IN) :: NX, NY
!   REAL,    INTENT(IN) :: X2D(NX,NY), Y2D(NX,NY)
!
! Routine to initialize CPMPXY3 (pass data, allocate working arrays,
! and, initialization)
!
!---------------------------------------
!
! SUBROUTINE NG_CPMPXY3( IMAP, XINP, YINP, XOUT, YOUT )
!
!   INTEGER, INTENT(IN   ) :: IMAP
!   REAL,    INTENT(IN   ) :: XINP
!   REAL,    INTENT(INOUT) :: YINP
!   REAL,    INTENT(  OUT) :: XOUT, YOUT
!
! This version of CPMPXY3 implements what has sometimes, in the past,
! been called a "parameterized distortion"
!
! If IMAP has the value 3, then, for given input values of XINP and
! YINP, where XINP lies in the interval [1,IDIM] and YINP lies in
! the interval [1,JDIM], CPMPXY3 generates output values of XOUT and
! YOUT, representing the transformed position of a point on an
! IDIMxJDIM grid of data.
!
! If IMAP has the value -3, CPMPXY3 performs the inverse transformation.
!
!---------------------------------------
!
! SUBROUTINE NG_CPMPXY3_FREE()
!
! Routine to deallocate working arrays
!
!---------------------------------------------------------------------
! CPMPXY3MAP - 2D xlon/ylat
!---------------------------------------------------------------------
!
! SUBROUTINE NG_CPMPXY3MAP_INIT(XLON, YLAT, NLON, NLAT)
!
!   INTEGER, INTENT(IN) :: NLON, NLAT
!   REAL,    INTENT(IN) :: XLON(NLON,NLAT), YLAT(NLON,NLAT)
!
! Routine to initialize CPMPXY3MAP (pass data, allocate working arrays,
! and, initialization)
!
!---------------------------------------
!
! SUBROUTINE NG_CPMPXY3MAP(IMAP, XINP, YINP, XOUT, YOUT)
!
!   INTEGER, INTENT(IN   ) :: IMAP
!   REAL,    INTENT(IN   ) :: XINP
!   REAL,    INTENT(INOUT) :: YINP
!   REAL,    INTENT(  OUT) :: XOUT, YOUT
!
! This version of CPMPXY implements what has sometimes, in the past,
! been called a "parameterized distortion", but it does it on the
! surface of the globe and then maps the globe as determined by the
! current state of EZMAP.  If IMAP has the value 3, then, for given
! input values of XINP and YINP, where XINP lies in the interval
! [1,IDIM] and YINP lies in the interval [1,JDIM], CPMPXY generates
! output values of XOUT and YOUT, representing the transformed position
! of a point on an IDIMxJDIM grid on the surface of the globe.  If IMAP
! has the value -3, CPMPXY performs the inverse transformation.
!
! For each (I,J), where 1.LE.I.LE.IDIM, and 1.LE.J.LE.JDIM, one of the
! vectors (XQSP(K,I,J),K=1,4) and (XQDP(K,I,J),K=1,4) is a 4-element
! vector containing the cosine of the latitude, the sine of the
! latitude, the cosine of the longitude, and the sine of the longitude
! of a point of the grid.  If ISOD is 0, the calling program must have
! set the values in XQSP; otherwise, it must have set the values in
! XQDP.  IBEG, IEND, JBEG, and JEND keep track of which box the last
! point inverse-transformed turned out to be in.  The calling routine
! is responsible for initializing all these values properly.
!
!---------------------------------------
!
! SUBROUTINE NG_CPMPXY3MAP_FREE()
!
! Routine to deallocate working arrays
!
!=====================================================================
! Reading netCDF NC3file
!=====================================================================
!
! SUBROUTINE NG_NC32TXT( nc3file, idata )
!
! SUBROUTINE NG_NC3INIT( nc3file ) ! Open/Allocate/Header
! SUBROUTINE NG_NC3RDCH( cvar, charray, n, ier ) ! ier=1/2 for incorrect cvar/n
! SUBROUTINE NG_NC3RDI1( cvar, i1array, n, ier )
! SUBROUTINE NG_NC3RDI2( cvar, i2array, n, ier )
! SUBROUTINE NG_NC3RDI4( cvar, i4array, n, ier )
! SUBROUTINE NG_NC3RDR4( cvar, r4array, n, ier )
! SUBROUTINE NG_NC3RDR8( cvar, r8array, n, ier )
! SUBROUTINE NG_NC3FREE() ! De-allocate/Close
!
! SUBROUTINE ng_nc3varb_lonlat( nc3file, nvb, npt )
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_NC32TXT( nc3file, idata )
!
!   CHARACTER(*), INTENT(IN) :: nc3file
!   INTEGER,      INTENT(IN) :: idata
!
! Routine to generate a text file describing the header (and data)
! information(s) of the given netCDF Version-1 file
!
! 1. input[a.nc] -> output[a.nc.cng]
!
! 2. idata = 0, header only
!            1, header + coordinate-variables (vector-variables)
!            2, header + scalar-variables + vector-variables
!         >= 3, header + all-variables
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_NC3INIT( nc3file )
!
!   CHARACTER(*), INTENT(IN) :: nc3file
!
! Open file, Reading header, Allocate working arrays
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_NC3RDCH( cvar, charray, n, ier )
!
!   CHARACTER(*), INTENT(IN   ) :: cvar
!   INTEGER,      INTENT(IN   ) :: n
!   CHARACTER(1), INTENT(  OUT) :: charray(n)
!   INTEGER,      INTENT(  OUT) :: ier
!
! Reading variable named "cvar" into CHARACTER 1byte Array "charray"
! ier = 1/2 for mismatch variable name/size, auto type conversion
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_NC3RDI1( cvar, i1array, n, ier )
!
!   CHARACTER(*), INTENT(IN   ) :: cvar
!   INTEGER,      INTENT(IN   ) :: n
!   INTEGER(i1),  INTENT(  OUT) :: i1array(n)
!   INTEGER,      INTENT(  OUT) :: ier
!
! Reading variable named "cvar" into INTEGER-1byte Array "i1array"
! ier = 1/2 for mismatch variable name/size, auto type conversion
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_NC3RDI2( cvar, i2array, n, ier )
!
!   CHARACTER(*), INTENT(IN   ) :: cvar
!   INTEGER,      INTENT(IN   ) :: n
!   INTEGER(i2),  INTENT(  OUT) :: i2array(n)
!   INTEGER,      INTENT(  OUT) :: ier
!
! Reading variable named "cvar" into INTEGER-2byte Array "i2array"
! ier = 1/2 for mismatch variable name/size, auto type conversion
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_NC3RDI4( cvar, i4array, n, ier )
!
!   CHARACTER(*), INTENT(IN   ) :: cvar
!   INTEGER,      INTENT(IN   ) :: n
!   INTEGER,      INTENT(  OUT) :: i4array(n)
!   INTEGER,      INTENT(  OUT) :: ier
!
! Reading variable named "cvar" into INTEGER-4byte Array "i4array"
! ier = 1/2 for mismatch variable name/size, auto type conversion
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_NC3RDR4( cvar, r4array, n, ier )
!
!   CHARACTER(*), INTENT(IN   ) :: cvar
!   INTEGER,      INTENT(IN   ) :: n
!   REAL,         INTENT(  OUT) :: r4array(n)
!   INTEGER,      INTENT(  OUT) :: ier
!
! Reading variable named "cvar" into REAL-4byte Array "r4array"
! ier = 1/2 for mismatch variable name/size, auto type conversion
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_NC3RDR8( cvar, r8array, n, ier )
!
!   CHARACTER(*), INTENT(IN   ) :: cvar
!   INTEGER,      INTENT(IN   ) :: n
!   REAL(r8),     INTENT(  OUT) :: r8array(n)
!   INTEGER,      INTENT(  OUT) :: ier
!
! Reading variable named "cvar" into REAL-8byte Array "r8array"
! ier = 1/2 for mismatch variable name/size, auto type conversion
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_NC3FREE()
!
! De_allocate working arrays, Close file
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_nc3varb_lonlat( nc3file, nvb, npt )
!
!   CHARACTER(*), INTENT(IN   ) :: nc3file
!   INTEGER,      INTENT(  OUT) :: nvb, npt
!
! Routine to write out "lon" and "lat" attribultes of all variables
! in specified NetCDF file
!
! Example:
!
!   INTEGER :: nvb, npt, ier, i
!   CHARACTER(12), ALLOCATABLE :: vb_name(:)
!   INTEGER,       ALLOCATABLE :: vb_npts(:)
!   REAL,          ALLOCATABLE :: vb_xlon(:), vb_ylat(:)
!   CHARACTER(12) :: text
!
!   !---------------
!
!   ! Read lon/lat from 'climdiv_polygons.nc', write to 'climdiv_polygons.nc.lonlat'
!   CALL ng_nc3varb_lonlat( 'climdiv_polygons.nc', nvb, npt )
!
!   ALLOCATE( vb_name(nvb), vb_npts(0:nvb), vb_xlon(npt), vb_ylat(npt), STAT=ier )
!   IF( ier /= 0 ) STOP 'Allocation error1'
!
!   OPEN( UNIT=11, FILE='climdiv_polygons.nc.lonlat')
!   vb_npts(0) = 0
!   DO i = 1, nvb
!     READ(11,*) text, n
!     vb_name(i) = TRIM(ADJUSTL(text))
!     vb_npts(i) = vb_npts(i-1) + n
!     READ(11,*) vb_xlon(vb_npts(i-1)+1:vb_npts(i))
!     READ(11,*) vb_ylat(vb_npts(i-1)+1:vb_npts(i))
!   END DO
!   CLOSE(UNIT=11)
!
!=====================================================================
! Reading GRIB GB2file
!=====================================================================
!
! SUBROUTINE NG_GB22TXT( gb2file )
!
! SUBROUTINE NG_GB2READ( gb2file, PDT_Number, PDT_Len, PDT_Array, n, gb2data,&
!                        GDT_Number, GDT_Len, GDT_Array, Missing_Value )
!
! SUBROUTINE ng_g2GDSLCGrid( GDT_Number, GDT_Len, GDT_Array, nlon, nlat, xlon2d, ylat2d,& ! GDT3.30: Lambert conformal
!                            LatParallel1, LatParallel2,& LonMeridian )
!
! SUBROUTINE ng_g2GDSSTGrid( GDT_Number, GDT_Len, GDT_Array, nlon, nlat, xlon2d, ylat2d,& ! GDT3.20: Polar Stereographic
!                            CenterLat, CenterLon )
!
! SUBROUTINE ng_g2GDSCEGrid( GDT_Number, GDT_Len, GDT_Array, nlon, nlat, xlon, ylat )     ! GDT3.0: Cylindrical Equidistant
!
! SUBROUTINE ng_g2GDSRLLGrid(GDT_Number, GDT_Len, GDT_Array, nlon, nlat, xlon2d, ylat2d,& ! GDT3.1: Rotate Cylindrical Equidistant
!                            Lon_of_SouthPole, Lat_of_SouthPole, Ang_of_Rotation )
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_GB22TXT( gb2file )
!
!   CHARACTER(*), INTENT(IN) :: gb2file
!
! Routine to reads GRIB2 file and write the inventory to a text file.
!
! Variables:
!
!   gb2file - Name of input GRIB2 data file
!
! Note: the inventory text file will be named "TRIM(gb2file)//'.txt'"
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_GB2READ(gb2file, PDT_Number, PDT_Len, PDT_Array, n, gb2data,&
!                       GDT_Number, GDT_Len, GDT_Array, Missing_Value)
!
! Routine to search selected field by product definition template number
! and the values of product definition template 4.n of the field, and then,
! return the unpacked field data and grid informations.
!
!   CHARACTER(*), INTENT(IN   ) :: gb2file
!   INTEGER,      INTENT(IN   ) :: PDT_Number, PDT_Len, PDT_Array(200)
!   INTEGER,      INTENT(IN   ) :: n
!   REAL,         INTENT(  OUT) :: gb2data(n)
!   INTEGER,      INTENT(  OUT), OPTIONAL :: GDT_Number, GDT_Len, GDT_Array(200)
!   REAL,         INTENT(  OUT), OPTIONAL :: Missing_Value
!
! Variables:
!
!   gb2file    - Input GRIB2 file
!
!   PDT_Number - Product Definition Template Number
!
!   PDT_Len    - Number of elements used in PDT_Array
!
!   PDT_Array  - Values of Product Definition Template 4.x of the field
!                for which to search ("x" is the PDT_Number)
!
!   n          - Declared size of array "gb2data"
!
!   gb2data    - Array of unpacked field data extracted from input GRIB2 file
!
!   GDT_Number - Grid Definition Template Number
!
!   GDT_Len    - Number of elements defined in GDT_Array
!
!   GDT_Array  - Values of Grid Definition Template 3.x of the field
!                ("x" is the GDT_Number)
!
!   Missing_Value - Value inserted at grid points where data was
!                   bit-mapped out
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_g2GDSLCGrid(GDT_Number, GDT_Len, GDT_Array, nlon, nlat,&
!                           xlon2d, ylat2d, LatParallel1, LatParallel2,&
!                           LonMeridian)
!
! Routine to calculate grids of GRIB-2 GDT3.30 (Lambert conformal).
!
!   INTEGER, INTENT(IN   ) :: GDT_Number, GDT_Len, LCGDT_Array(200)
!   INTEGER, INTENT(IN   ) :: nlon, nlat
!   REAL,    INTENT(  OUT) :: xlon2d(nlon,nlat), ylat2d(nlon,nlat)
!   REAL,    INTENT(  OUT) :: LatParallel1, LatParallel2, LonMeridian
!
! Variables:
!
!   GDT_Number   - Grid Definition Template Number, should be "0"
!
!   GDT_Len      - Number of elements defined in GDT_Array
!
!   GDT_Array    - Values of Grid Definition Template 3.30
!
!   nlon         - First dimension (x,longitude) of coordinates arrays
!
!   nlat         - Second dimension (y,latitude) of coordinates arrays
!
!   xlon2d       - Longitude (2d curvilinear) coordinates array
!
!   ylat2d       - Latitude (2d curvilinear) coordinates array
!
!   LatParallel1 - First (latitude) standard parallel
!
!   LatParallel2 - Second (latitude) standard parallel
!
!   LonMeridian  - Central (longitude) meridian of the projection
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_g2GDSSTGrid(GDT_Number, GDT_Len, GDT_Array, nlon, nlat,&
!                           xlon2d, ylat2d, CenterLat, CenterLon)
!
! Routine to calculate grids of GRIB-2 GDT3.20 (Polar Stereographic).
!
!   INTEGER, INTENT(IN   ) :: GDT_Number, GDT_Len, GDT_Array(200)
!   INTEGER, INTENT(IN   ) :: nlon, nlat
!   REAL,    INTENT(  OUT) :: xlon2d(nlon,nlat), ylat2d(nlon,nlat)
!   REAL,    INTENT(  OUT) :: CenterLat, CenterLon
!
! Variables:
!
!   GDT_Number - Grid Definition Template Number, should be "0"
!
!   GDT_Len    - Number of elements defined in GDT_Array
!
!   GDT_Array  - Values of Grid Definition Template 3.20
!
!   nlon       - First dimension (x,longitude) of coordinates arrays
!
!   nlat       - Second dimension (y,latitude) of coordinates arrays
!
!   xlon2d     - Longitude (2d curvilinear) coordinates array
!
!   ylat2d     - Latitude (2d curvilinear) coordinates array
!
!   CenterLat  - THe center latitude
!                = +90.0, for North Pole is on the projection plane, or,
!                = -90.0, for South Pole is on the projection plane
!
!   CenterLon  - The center longitude, i.e., orientation of grid
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_g2GDSCEGrid(GDT_Number, GDT_Len, GDT_Array, nlon, nlat,&
!                           xlon, ylat)
!
! Routine to calculate grids of GRIB-2 GDT3.0 (Cylindrical Equidistant).
!
!   INTEGER, INTENT(IN   ) :: GDT_Number, GDT_Len, GDT_Array(200)
!   INTEGER, INTENT(IN   ) :: nlon, nlat
!   REAL,    INTENT(  OUT) :: xlon(nlon), ylat(nlat)
!
! Variables:
!
!   GDT_Number - Grid Definition Template Number, should be "0"
!
!   GDT_Len    - Number of elements defined in GDT_Array
!
!   GDT_Array  - Values of Grid Definition Template 3.0
!
!   nlon       - Dimension (x,longitude) of xlon
!
!   nlat       - Dimension (y,latitude) of ylat
!
!   xlon       - Longitude (1d linear) coordinates array
!
!   ylat       - Latitude (1d linear) coordinates array
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_g2GDSRLLGrid(GDT_Number, GDT_Len, GDT_Array, nlon, nlat, xlon2d, ylat2d,&
!                           Lon_of_SouthPole, Lat_of_SouthPole, Ang_of_Rotation)
!
! Routine to calculate grids of GRIB-2 GDT3.1 (Rotate Cylindrical Equidistant).
!
!   INTEGER, INTENT(IN   ) :: GDT_Number, GDT_Len, GDT_Array(200)
!   INTEGER, INTENT(IN   ) :: nlon, nlat
!   REAL,    INTENT(  OUT) :: xlon2d(nlon,nlat), ylat2d(nlon,nlat)
!   REAL,    INTENT(  OUT) :: Lon_of_SouthPole, Lat_of_SouthPole, Ang_of_Rotation
!
! Variables:
!
!   GDT_Number       - Grid Definition Template Number, should be "1"
!
!   GDT_Len          - Number of elements defined in GDT_Array
!
!   GDT_Array        - Values of Grid Definition Template 3.1
!
!   nlon             - First dimension (x,longitude) of coordinates arrays
!
!   nlat             - Second dimension (y,latitude) of coordinates arrays
!
!   xlon2d           - Longitude (2d curvilinear) coordinates array
!
!   ylat2d           - Latitude (2d curvilinear) coordinates array
!
!   Lon_of_SouthPole - Longitude of the southern pole of projection
!
!   Lat_of_SouthPole - Latitude of the southern pole of projection
!
!   Ang_of_Rotation  - Angle of rotation of projection
!
!=====================================================================
! Shapefile
!=====================================================================
!
! SUBROUTINE NG_DBF2TXT(DBFfile)
! SUBROUTINE NG_SHP2TXT(SHPfile)
! SUBROUTINE NG_SHX2TXT(SHXfile)
!
! SUBROUTINE ng_shp_get_n  (DBFfile, nrec, ncol)
! SUBROUTINE ng_shp_get_box(SHPfile, shapetype, minlon, maxlon, minlat, maxlat)
!
! SUBROUTINE ng_shp_get_col(DBFfile, icol, attrib, nrec)
!
! SUBROUTINE ng_shp_get_xy1(SHPfile, xlon, ylat, nrec)
!
! SUBROUTINE ng_shp_get_xyp(SHPfile, SHXfile, irec, xlon, ylat, n, list, m, npoints, nparts)
!
! SUBROUTINE ng_shp_add_polymarkers  (shapefile, color, nrec, imarker, ht, dg)
!
! SUBROUTINE ng_shp_add_polylines    (shapefile)
! SUBROUTINE ng_shp_add_polylines2   (shapefile, color, nrec)
!
! SUBROUTINE ng_shp_add_polygons     (shapefile, color, nrec)
! SUBROUTINE ng_shp_add_polygons_ave (shapefile, nlon, nlat, xlon, ylat, data,&
!                                     shpmask, nrec, clevl, color, nclv, spv, spvcolor)
!
! SUBROUTINE ng_shp_create_mask (shapefile, nlon, nlat, xlon, ylat, mask)
! SUBROUTINE ng_shp_create_mask2(shapefile, nlon, nlat, xlon, ylat, mask, shpmask, nrec)
! SUBROUTINE ng_shp_create_mask3(shapefile, nlon, nlat, xlon, ylat, mask, delta_kilometer)
!
! SUBROUTINE ng_shp_create_2dmask (shapefile, nlon, nlat, xlon, ylat, mask)
! SUBROUTINE ng_shp_create_2dmask2(shapefile, nlon, nlat, xlon, ylat, mask, shpmask, nrec)
!
! LOGICAL FUNCTION ng_gc_inout(plat, plon, qlat, qlon, npts)
!
! SUBROUTINE ng_landsea_mask( basemap, nlon, nlat, tlon, tlat, maskarray )
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_DBF2TXT(DBFfile)
!
!   CHARACTER(*), INTENT(IN) :: DBFfile
!
! Convert Shapefile attribute format ".dbf" file from "binary" to "text"
!
! https://en.wikipedia.org/wiki/Shapefile
! http://www.dbf2002.com/dbf-file-format.html
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_SHP2TXT(SHPfile)
!
!   CHARACTER(*), INTENT(IN) :: SHPfile
!
! Convert Shapefile shape format ".shp" file from "binary" to "text"
!
! http://dl.maptools.org/dl/shapelib/shapefile.pdf
! https://zh.wikipedia.org/wiki/Shapefile
! https://en.wikipedia.org/wiki/Shapefile
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_SHX2TXT(SHXfile)
!
!   CHARACTER(*), INTENT(IN) :: SHXfile
!
! Convert Shapefile shape index format ".shx" file from "binary" to "text"
!
! http://dl.maptools.org/dl/shapelib/shapefile.pdf
! https://zh.wikipedia.org/wiki/Shapefile
! https://en.wikipedia.org/wiki/Shapefile
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_get_n(DBFfile, nrec, ncol)
!
!   CHARACTER(*), INTENT(IN   ) :: DBFfile
!   INTEGER,      INTENT(  OUT) :: nrec, ncol
!
! Routine to get the number of "records" and "columns" from shape DBFfile
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_get_box(SHPfile, shapetype, minlon, maxlon, minlat, maxlat)
!
!   CHARACTER(*), INTENT(IN   ) :: SHPfile
!   INTEGER,      INTENT(  OUT) :: shapetype
!   REAL,         INTENT(  OUT) :: minlon, maxlon, minlat, maxlat
!
! Routine to get ...
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_get_col(DBFfile, icol, attrib, nrec)
!
!   CHARACTER(*), INTENT(IN   ) :: DBFfile
!   INTEGER,      INTENT(IN   ) :: icol, nrec
!   CHARACTER(*), INTENT(  OUT) :: attrib(nrec)
!
! Routine to get the "icol"th column attributes "attrib" from shape DBFfile
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_get_xy1(SHPfile, xlon, ylat, nrec)
!
!   CHARACTER(*), INTENT(IN   ) :: SHPfile
!   INTEGER,      INTENT(IN   ) ::  nrec
!   REAL,         INTENT(  OUT) :: xlon(nrec), ylat(nrec)
!
! Routine to get all xlon/ylat data from ShapeType=1 (Point) shapefile
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_get_xyp(SHPfile, SHXfile, irec, xlon, ylat,&
!                           n, list, m, npoints, nparts)
!
!   CHARACTER(*), INTENT(IN   ) :: SHPfile, SHXfile
!   INTEGER,      INTENT(IN   ) :: irec, n, m
!   REAL,         INTENT(  OUT) :: xlon(n), ylat(n)
!   INTEGER,      INTENT(  OUT) :: list(m)
!   INTEGER,      INTENT(  OUT) :: npoints, nparts
!
! Routine to get the xlon/ylat data of "irec"th record from shape SHPfile
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_add_polymarkers( shapefile, color, nrec, imarker, ht, dg )
!
!   CHARACTER(*), INTENT(IN) :: shapefile
!   INTEGER,      INTENT(IN) :: nrec
!   INTEGER,      INTENT(IN) :: color(nrec)
!   INTEGER,      INTENT(IN) :: imarker
!   REAL,         INTENT(IN) :: ht, dg
!
! Routine to draw shapefile point symbol
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_add_polylines( shapefile )
!
!   CHARACTER(*), INTENT(IN) :: shapefile
!
! Routine to draw shapefile polygon (Type 5) or polyline (Type 3) data
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_add_polylines2( shapefile, color, nrec )
!
!   CHARACTER(*), INTENT(IN) :: shapefile
!   INTEGER,      INTENT(IN) :: nrec
!   INTEGER,      INTENT(IN) :: color(nrec)
!
! Routine to draw shapefile polygon (Type 5) or polyline (Type 3) data
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_add_polygons( shapefile, color, nrec )
!
!   CHARACTER(*), INTENT(IN) :: shapefile
!   INTEGER,      INTENT(IN) :: nrec
!   INTEGER,      INTENT(IN) :: color(nrec)
!
! Routine to fill shapefile polygon (ShapeType 5)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_add_polygons_ave( shapefile, nlon, nlat, xlon, ylat data,&
!                                     shpmask, nrec, clevl, color, nclv, spv, spvcolor)
!
!   CHARACTER(*), INTENT(IN) :: shapefile
!   INTEGER,      INTENT(IN) :: nlon, nlat, nrec, nclv
!   REAL,         INTENT(IN) :: xlon(nlon), ylat(nlat), data(nlon,nlat)
!   INTEGER,      INTENT(IN) :: shpmask(nrec)
!   REAL,         INTENT(IN) :: clevl(nclv)
!   INTEGER,      INTENT(IN) :: color(nclv+1)
!   REAL,         INTENT(IN) :: spv
!   INTEGER,      INTENT(IN) :: spvcolor
!
! Routine to fill shapefile polygons in a color based on a data average.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_create_mask( shapefile, nlon, nlat, xlon, ylat, mask )
!
!   CHARACTER(*), INTENT(IN   ) :: shapefile
!   INTEGER,      INTENT(IN   ) :: nlon, nlat
!   REAL,         INTENT(IN   ) :: xlon(nlon), ylat(nlat)
!   INTEGER,      INTENT(  OUT) :: mask(nlon,nlat)
!
! This subroutine takes a shapefile of type "polygon" and xlon/ylat
! coordinate arrays, and creates a mask array that contains 0s and 1s,
! depending if the xlat/ylon values are inside (1) or outside (0) of
! the shapefile polygons
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_create_mask2( shapefile, nlon, nlat, xlon, ylat,&
!                                 mask, shpmask, nrec)
!
!   CHARACTER(*), INTENT(IN   ) :: shapefile
!   INTEGER,      INTENT(IN   ) :: nlon, nlat, nrec
!   INTEGER,      INTENT(IN   ) :: shpmask(nrec)
!   REAL,         INTENT(IN   ) :: xlon(nlon), ylat(nlat)
!   INTEGER,      INTENT(  OUT) :: mask(nlon,nlat)
!
! This subroutine takes a shapefile of type "polygon" and xlon/ylat
! coordinate arrays, and creates a mask array that contains 0s and 1s,
! depending if the xlat/ylon values are inside (1) or outside (0) of
! the shapefile polygons
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_create_mask3( shapefile, nlon, nlat, xlon, ylat,&
!                                 mask, delta_kilometer )
!
!   CHARACTER(*), INTENT(IN   ) :: shapefile
!   INTEGER,      INTENT(IN   ) :: nlon, nlat
!   REAL,         INTENT(IN   ) :: xlon(nlon), ylat(nlat)
!   INTEGER,      INTENT(  OUT) :: mask(nlon,nlat)
!   REAL,         INTENT(IN   ) :: delta_kilometer
!
! This subroutine takes a shapefile of type "polygon" and xlon/ylat
! coordinate arrays, and creates a mask array that contains 0s and 1s,
! depending if the xlat/ylon values are inside (1) or outside (0) of
! the shapefile polygons
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_create_2dmask( shapefile, nlon, nlat, xlon, ylat,&
!                                  mask )
!
!   CHARACTER(*), INTENT(IN   ) :: shapefile
!   INTEGER,      INTENT(IN   ) :: nlon, nlat
!   REAL,         INTENT(IN   ) :: xlon(nlon,nlat), ylat(nlon,nlat)
!   INTEGER,      INTENT(  OUT) :: mask(nlon,nlat)
!
! This subroutine takes a shapefile of type "polygon" and xlon/ylat
! coordinate arrays, and creates a mask array that contains 0s and 1s,
! depending if the "2d coordinates array" xlat/ylon values are inside
! (1) or outside (0) of the shapefile polygons
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_shp_create_2dmask2( shapefile, nlon, nlat, xlon, ylat,&
!                                   mask, shpmask, nrec)
!
!   CHARACTER(*), INTENT(IN   ) :: shapefile
!   INTEGER,      INTENT(IN   ) :: nlon, nlat, nrec
!   INTEGER,      INTENT(IN   ) :: shpmask(nrec)
!   REAL,         INTENT(IN   ) :: xlon(nlon,nlat), ylat(nlon,nlat)
!   INTEGER,      INTENT(  OUT) :: mask(nlon,nlat)
!
! This subroutine takes a shapefile of type "polygon" and xlon/ylat
! coordinate arrays, and creates a mask array that contains 0s and 1s,
! depending if the "2d coordinates array" xlat/ylon values are inside
! (1) or outside (0) of the shapefile polygons
!
!-------------------------------------------------------------------
!
! LOGICAL FUNCTION ng_gc_inout(plat, plon, qlat, qlon, npts)
!
!   REAL,    INTENT(IN) :: plat, plon
!   INTEGER, INTENT(IN) :: npts
!   REAL,    INTENT(IN) :: qlat(npts), qlon(npts)
!
! This function determines if the coordinate (plat,plon) is inside
! or outside of the spherical patch (qlat(i),qlon(i)),i=1,npts).
!
! .TRUE. is returned if in, .FALSE. otherwise.
!
! Notes:
!
! 1. It is assumed that the polygons do not cross themselves and
!    that the vertices can be contained in a hemisphere.
!
! 2. If the polygons are not closed (that is, if the first listed
!    vertex doesn't equal the last), then this function will close
!    the polygon for you.
!
! 3. A point is considered inside if it is strictly inside or
!    on boundary arc.
!
! 4. Given the discrete nature of floating point arithmetic,
!    a point is considered to be on a boundary arc if it is
!    within 1.0E-10 degrees of it.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_landsea_mask( basemap, nlon, nlat, tlon, tlat, maskarray )
!
!   INTEGER, INTENT(IN   ) :: basemap(360,180)
!   INTEGER, INTENT(IN   ) :: nlon, nlat
!   REAL,    INTENT(IN   ) :: tlon(nlon), tlat(nlat)
!   INTEGER, INTENT(  OUT) :: maskarray(nlon,nlat)
!
! Routine to return a grid that contains a land/sea mask given any
! latitude and longitude array.
!
! basemap : A two-dimensional array, size of (360,180), contains a 1 x 1
!           degree grid of baseline land/sea mask.
!
! tlon    : A one-dimensional array, size of (nlon), of longitudes.
!           Acceptable values range from -180 to 359.99.
!
! tlat    : A one-dimensional array, size of (nlat), of latitudes.
!
! maskarray : A two-dimensional array, size of (nlon,nlat), is returned.
!             It contains five possible values: 0=ocean, 1=land, 2=lake,
!             3=small island, 4=ice shelf.
!
!=====================================================================
! Spherical Harmonics
!=====================================================================
!
! SUBROUTINE ng_lderuvg(nlon, nlat, u, v, uy, vy)
! SUBROUTINE ng_lderuvf(nlon, nlat, u, v, uy, vy)
!
! SUBROUTINE ng_gradsg(nlon, nlat, z, gzx, gzy)
! SUBROUTINE ng_gradsf(nlon, nlat, z, gzx, gzy)
!
! SUBROUTINE ng_lapsg(nlon, nlat, z, zlap)
! SUBROUTINE ng_lapsf(nlon, nlat, z, zlap)
!
! SUBROUTINE ng_lapvg(nlon, nlat, u, v, ulap, vlap)
! SUBROUTINE ng_lapvf(nlon, nlat, u, v, ulap, vlap)
!
! SUBROUTINE ng_igradsg(nlon, nlat, gzx, gzy, z)
! SUBROUTINE ng_igradsf(nlon, nlat, gzx, gzy, z)
!
! SUBROUTINE ng_ilapsg(nlon, nlat, zlap, zlmbda, z)
! SUBROUTINE ng_ilapsf(nlon, nlat, zlap, zlmbda, z)
!
! SUBROUTINE ng_ilapvg(nlon, nlat, ulap, vlap, u, v)
! SUBROUTINE ng_ilapvf(nlon, nlat, ulap, vlap, u, v)
!
! SUBROUTINE ng_uv2vrg(nlon, nlat, u, v, vr)
! SUBROUTINE ng_uv2vrf(nlon, nlat, u, v, vr)
!
! SUBROUTINE ng_uv2dvg(nlon, nlat, u, v, dv)
! SUBROUTINE ng_uv2dvf(nlon, nlat, u, v, dv)
!
! SUBROUTINE ng_uv2vrdvg(nlon, nlat, u, v, vr, dv)
! SUBROUTINE ng_uv2vrdvf(nlon, nlat, u, v, vr, dv)
!
! SUBROUTINE ng_uv2sfvpg(nlon, nlat, u, v, sf, vp)
! SUBROUTINE ng_uv2sfvpf(nlon, nlat, u, v, sf, vp)
!
! SUBROUTINE ng_vr2uvg(nlon, nlat, vort, ur, vr)
! SUBROUTINE ng_vr2uvf(nlon, nlat, vort, ur, vr)
!
! SUBROUTINE ng_dv2uvg(nlon, nlat, dv, ud, vd)
! SUBROUTINE ng_dv2uvf(nlon, nlat, dv, ud, vd)
!
! SUBROUTINE ng_vrdv2uvg(nlon, nlat, vr, dv, u, v)
! SUBROUTINE ng_vrdv2uvf(nlon, nlat, vr, dv, u, v)
!
! SUBROUTINE ng_sfvp2uvg(nlon, nlat, sf, vp, u, v)
! SUBROUTINE ng_sfvp2uvf(nlon, nlat, sf, vp, u, v)
!
! SUBROUTINE ng_uv2vr_cfd(nlon, nlat, xlon, ylat, u, v, xmsg, iopt, rv, ier)
! SUBROUTINE ng_uv2dv_cfd(nlon, nlat, xlon, ylat, u, v, xmsg, iopt, dv, ier)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_lderuvg(nlon, nlat, u, v, uy, vy)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: u (nlon,nlat), v (nlon,nlat)
!   REAL,    INTENT(  OUT) :: uy(nlon,nlat), vy(nlon,nlat)
!
! Computes the latitudinal derivatives using spherical harmonics,
! given vector components (u,v) on a gaussian grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_lderuvf(nlon, nlat, u, v, uy, vy)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: u (nlon,nlat), v (nlon,nlat)
!   REAL,    INTENT(  OUT) :: uy(nlon,nlat), vy(nlon,nlat)
!
! Computes the latitudinal derivatives using spherical harmonics,
! given vector components (u,v) on a fixed grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_gradsg(nlon, nlat, z, gzx, gzy)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: z(nlon,nlat)
!   REAL,    INTENT(  OUT) :: gzx(nlon,nlat), gzy(nlon,nlat)
!
! Computes the gradient of an array that is on a gaussian grid using
! spherical harmonics.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_gradsf(nlon, nlat, z, gzx, gzy)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: z(nlon,nlat)
!   REAL,    INTENT(  OUT) :: gzx(nlon,nlat), gzy(nlon,nlat)
!
! Computes the gradient of an array that is on a fixed grid using
! spherical harmonics.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_lapsg(nlon, nlat, z, zlap)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: z(nlon,nlat)
!   REAL,    INTENT(  OUT) :: zlap(nlon,nlat)
!
! Computes the Laplacian using spherical harmonics, given a scalar
! z on a gaussian grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_lapsf(nlon, nlat, z, zlap)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: z(nlon,nlat)
!   REAL,    INTENT(  OUT) :: zlap(nlon,nlat)
!
! Computes the Laplacian using spherical harmonics, given a scalar
! z on a fixed grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_lapvg(nlon, nlat, u, v, ulap, vlap)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: u   (nlon,nlat), v   (nlon,nlat)
!   REAL,    INTENT(  OUT) :: ulap(nlon,nlat), vlap(nlon,nlat)
!
! Computes the vector Laplacian using spherical harmonics, given a
! vector quantity (u,v) on a gaussian grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_lapvf(nlon, nlat, u, v, ulap, vlap)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: u   (nlon,nlat), v   (nlon,nlat)
!   REAL,    INTENT(  OUT) :: ulap(nlon,nlat), vlap(nlon,nlat)
!
! Computes the vector Laplacian using spherical harmonics, given a
! vector quantity (u,v) on a fixed grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_igradsg(nlon, nlat, gzx, gzy, z)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: gzx(nlon,nlat), gzy(nlon,nlat)
!   REAL,    INTENT(  OUT) :: z(nlon,nlat)
!
! Computes a scalar array from its gradient components on a gaussian
! grid using spherical harmonics.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_igradsf(nlon, nlat, gzx, gzy, z)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: gzx(nlon,nlat), gzy(nlon,nlat)
!   REAL,    INTENT(  OUT) :: z(nlon,nlat)
!
! Computes a scalar array from its gradient components on a fixed
! grid using spherical harmonics.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_ilapsg(nlon, nlat, zlap, zlmbda, Z)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: zlap(nlon,nlat), zlmbda
!   REAL,    INTENT(  OUT) :: z(nlon,nlat)
!
! Inverts the Laplacian (on a gaussian grid) using spherical harmonics.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_ilapsf(nlon, nlat, zlap, zlmbda, Z)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: zlap(nlon,nlat), zlmbda
!   REAL,    INTENT(  OUT) :: z(nlon,nlat)
!
! Inverts the Laplacian (on a fixed grid) using spherical harmonics.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_ilapvg(nlon, nlat, ulap, vlap, u, v)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: ulap(nlon,nlat), vlap(nlon,nlat)
!   REAL,    INTENT(  OUT) :: u   (nlon,nlat), v   (nlon,nlat)
!
! Inverts the vector Laplacian (on a gaussian grid) using spherical
! harmonics.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_ilapvf(nlon, nlat, ulap, vlap, u, v)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: ulap(nlon,nlat), vlap(nlon,nlat)
!   REAL,    INTENT(  OUT) :: u   (nlon,nlat), v   (nlon,nlat)
!
! Inverts the vector Laplacian (on a fixed grid) using spherical
! harmonics.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_uv2vrg(nlon, nlat, u, v, vr)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: u(nlon,nlat), v(nlon,nlat)
!   REAL,    INTENT(  OUT) :: vr(nlon,nlat)
!
! Computes the vorticity via spherical harmonics, given the u and v
! wind components on a gaussian grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_uv2vrf(nlon, nlat, u, v, vr)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: u(nlon,nlat), v(nlon,nlat)
!   REAL,    INTENT(  OUT) :: vr(nlon,nlat)
!
! Computes the vorticity via spherical harmonics, given the u and v
! wind components on a fixed grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_uv2dvg(nlon, nlat, u, v, dv)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: u(nlon,nlat), v(nlon,nlat)
!   REAL,    INTENT(  OUT) :: dv(nlon,nlat)
!
! Computes the divergence using spherical harmonics given the u and v
! wind components on a gaussian grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_uv2dvf(nlon, nlat, u, v, dv)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: u(nlon,nlat), v(nlon,nlat)
!   REAL,    INTENT(  OUT) :: dv(nlon,nlat)
!
! Computes the divergence using spherical harmonics given the u and v
! wind components on a fixed grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_uv2vrdvg(nlon, nlat, u, v, vr, dv)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: u (nlon,nlat), v (nlon,nlat)
!   REAL,    INTENT(  OUT) :: vr(nlon,nlat), dv(nlon,nlat)
!
! Computes the vorticity and divergence via spherical harmonics,
! given the u and v wind components on a gaussian grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_uv2vrdvf(nlon, nlat, u, v, vr, dv)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: u (nlon,nlat), v (nlon,nlat)
!   REAL,    INTENT(  OUT) :: vr(nlon,nlat), dv(nlon,nlat)
!
! Computes the vorticity and divergence via spherical harmonics,
! given the u and v wind components on a fixed grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_uv2sfvpg(nlon, nlat, u, v, sf, vp)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: u (nlon,nlat), v (nlon,nlat)
!   REAL,    INTENT(  OUT) :: sf(nlon,nlat), vp(nlon,nlat)
!
! Computes the stream function and velocity potential via spherical
! harmonics given u and v on a gaussian grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_uv2sfvpf(nlon, nlat, u, v, sf, vp)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: u (nlon,nlat), v (nlon,nlat)
!   REAL,    INTENT(  OUT) :: sf(nlon,nlat), vp(nlon,nlat)
!
! Computes the stream function and velocity potential via spherical
! harmonics given u and v on a fixed grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_vr2uvg(nlon, nlat, vort, ur, vr)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: vort(nlon,nlat)
!   REAL,    INTENT(  OUT) :: ur(nlon,nlat), vr(nlon,nlat)
!
! Computes the rotational wind components via spherical harmonics,
! given an array containing relative vorticity on a gaussian grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_vr2uvf(nlon, nlat, vort, ur, vr)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: vort(nlon,nlat)
!   REAL,    INTENT(  OUT) :: ur(nlon,nlat), vr(nlon,nlat)
!
! Computes the rotational wind components via spherical harmonics,
! given an array containing relative vorticity on a fixed grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_dv2uvg(nlon, nlat, dv, ud, vd)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: dv(nlon,nlat)
!   REAL,    INTENT(  OUT) :: ud(nlon,nlat), vd(nlon,nlat)
!
! Computes the divergent (irrotational) wind components for a gaussian
! grid via spherical harmonics.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_dv2uvf(nlon, nlat, dv, ud, vd)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: dv(nlon,nlat)
!   REAL,    INTENT(  OUT) :: ud(nlon,nlat), vd(nlon,nlat)
!
! Computes the divergent (irrotational) wind components for a fixed
! grid via spherical harmonics.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_vrdv2uvg(nlon, nlat, vr, dv, u, v)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: vr(nlon,nlat), dv(nlon,nlat)
!   REAL,    INTENT(  OUT) :: u (nlon,nlat), v (nlon,nlat)
!
! Computes the wind components via spherical harmonics, given
! vorticity and divergence on a gaussian grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_vrdv2uvf(nlon, nlat, vr, dv, u, v)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: vr(nlon,nlat), dv(nlon,nlat)
!   REAL,    INTENT(  OUT) :: u (nlon,nlat), v (nlon,nlat)
!
! Computes the wind components via spherical harmonics, given
! vorticity and divergence on a fixed grid.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_sfvp2uvg(nlon, nlat, sf, vp, u, v)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: sf(nlon,nlat), vp(nlon,nlat)
!   REAL,    INTENT(  OUT) :: u (nlon,nlat), v (nlon,nlat)
!
! Computes the wind components given stream function and velocity
! potential (on a gaussian grid) via spherical harmonics.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_sfvp2uvf(nlon, nlat, sf, vp, u, v)
!
!   INTEGER, INTENT(IN   ) :: nlat, nlon
!   REAL,    INTENT(IN   ) :: sf(nlon,nlat), vp(nlon,nlat)
!   REAL,    INTENT(  OUT) :: u (nlon,nlat), v (nlon,nlat)
!
! Computes the wind components given stream function and velocity
! potential (on a fixed grid) via spherical harmonics.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_uv2vr_cfd(nlon, nlat, xlon, ylat, u, v, xmsg, iopt, rv, ier)
!
!   INTEGER, INTENT(IN   ) :: nlon, nlat
!   REAL,    INTENT(IN   ) :: xlon(nlon), ylat(nlat)
!   REAL,    INTENT(IN   ) :: u(nlon,nlat), v(nlon,nlat), xmsg
!   INTEGER, INTENT(IN   ) :: iopt
!   REAL,    INTENT(  OUT) :: rv(nlon,nlat)
!   INTEGER, INTENT(  OUT) :: ier
!
! relative vorticity via centered finite difference approach (rv)
! .  rv = dv/dx-du/dy+(u/a)tan(ylat)   where "d" means partial derivitive
! reference: Bluestein p113-114 [was not the original reference]
!            Halt-Martin p314   [ nothing on rv]
!
! assumptions:
! .   (1) latitudes  monotonically increasing  [eg: ylat(2) > ylat(1)]
! .                  latitudes may be unequally spaced
! .   (2) longitudes monotonically increasing  [eg: xlon(2) > xlon(1)]
! .                  longitudes are assmed to be equally spaced
! .   (3) if iopt=1 then the grids are cyclic in x
! .                  eg: for T42 grid mlon=128, nlat=64
! .                      cyclic point should NOT be included
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_uv2dv_cfd(nlon, nlat, xlon, ylat, u, v, xmsg, iopt, dv, ier)
!
!   INTEGER, INTENT(IN   ) :: nlon, nlat
!   REAL,    INTENT(IN   ) :: xlon(nlon), ylat(nlat)
!   REAL,    INTENT(IN   ) :: u(nlon,nlat), v(nlon,nlat), xmsg
!   INTEGER, INTENT(IN   ) :: iopt
!   REAL,    INTENT(  OUT) :: dv(nlon,nlat)
!   INTEGER, INTENT(  OUT) :: ier
!
! divergence via centered finite differences
! . div = dv/dy+du/dx-(v/re)*tan(ylat)  where "d" ==> partial derivitive
!
! reference: Bluestein p113-114
!            Halt-Martin p314
!
! assumptions:
! .   (1) latitudes  monotonically increasing  [eg: ylat(2) > ylat(1)]
! .                  latitudes may be unequally spaced
! .   (2) longitudes monotonically increasing  [eg: xlon(2) > xlon(1)]
! .                  longitudes are assmed to be equally spaced
! .   (3) if iopt=1 then the grids are cyclic in x
! .                  eg: for T42 grid mlon=128, nlat=64
! .                      cyclic point should NOT be included
!
!=====================================================================
! Longitudes and Latitudes
!=====================================================================
!
! SUBROUTINE ng_lonGlobeF (mlon, xlon)
! SUBROUTINE ng_lonGlobeFo(mlon, xlon)
!
! SUBROUTINE ng_latGlobeF (nlat, ylat)
! SUBROUTINE ng_latGlobeFo(nlat, ylat)
!
! SUBROUTINE ng_latGau   (nlat, ylat)
! SUBROUTINE ng_latGau2  (nlat, ylat, ywgt)
!
! SUBROUTINE ng_latGauWgt(nlat, ywgt)
! SUBROUTINE ng_latRegWgt(nlat, ylat, ywgt, iopt)
!
! SUBROUTINE ng_lonFlip(nlon, m, xlon, varb)
! SUBROUTINE ng_lonPivot(nlon, m, pivotLon, xlon, varb)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_lonGlobeF(mlon, xlon)
!
!   INTEGER, INTENT(IN   ) :: mlon
!   REAL,    INTENT(  OUT) :: xlon(mlon)
!
!---------------------------------------
!
! D. Shea
! Generate longitudes for a Fixed global grid
! mlon = 128
! lon  = lonGlobeF (mlon, "lon", "longitude", "degrees_east")
! lon will run from 0->"whatever"
!
! If u want the initial lon to be -180., then upon return
!          lon = (/ lon - 180. /)  ; subtract 180 from all values
!          lon&lon = lon           ; make coord
!
! set mlon@double = True if double precision is desired
!
! undef ("lonGlobeF")
! function lonGlobeF(mlon:integer,dimName:string,longName:string,units:string)
! local dlon, lon
! begin
!   if (isatt(mlon,"double") .and. mlon@double) then
!       dlon      = new ( 1, "double")
!   else
!       dlon      = new ( 1, "float")
!   end if
!   delete (dlon@_FillValue)
!
!   dlon          = 360./mlon           ; output lon
!   lon           = ispan ( 0,mlon-1,1 )*dlon
!   lon!0         = dimName
!   lon@long_name = longName
!   lon@units     = units
!   lon&$dimName$ = lon
!   return (lon)
! end
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_lonGlobeFo(mlon, xlon)
!
!   INTEGER, INTENT(IN   ) :: mlon
!   REAL,    INTENT(  OUT) :: xlon(mlon)
!
!---------------------------------------
!
! D. Shea
! Generate longitudes for a Fixed-OfGSUNset global grid
! Example: lon = lonGlobeFo (72, "lon", "longitude", "degrees_east")
!          lon will run from -> 2.5 to 357.5 in the above example
!
! If u want the initial lon to be, say, -177.5,, then upon return
!          lon = (/ lon - 180. /)  ; subtract 180 from all values
!          lon&lon = lon           ; make coord
!
! set mlon@double = True if double precision is desired
!
! undef ("lonGlobeFo")
! function lonGlobeFo(mlon:integer,dimName:string,longName:string,units:string)
! local dlon, offset, lon
! begin
!   if (isatt(mlon,"double") .and. mlon@double) then
!       dlon      = new ( 1, "double")
!   else
!       dlon      = new ( 1, "float")
!   end if
!   delete (dlon@_FillValue)
!
!   dlon          = 360./mlon           ; output lon
!   offset        = dlon*0.5
!   lon           = ispan ( 0,mlon-1,1 )*dlon + offset
!   lon!0         = dimName
!   lon@long_name = longName
!   lon@units     = units
!   lon&$dimName$ = lon
!   return (lon)
! end
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_latGlobeF(nlat, ylat)
!
!   INTEGER, INTENT(IN   ) :: nlat
!   REAL,    INTENT(  OUT) :: ylat(nlat)
!
!---------------------------------------
!
! D. Shea
! Generate latitudes for a Fixed global grid
! nlat= 73
! lat = latGlobeF (nlat, "lat", "latitude", "degrees_north")
! lat will run from -90 -> +90
!
! set nlat@double = True if double precision is desired
!
! undef ("latGlobeF")
! function latGlobeF(nlat:integer,dimName:string,longName:string,units:string)
! local dlat, lat
! begin
!   if (isatt(nlat,"double") .and. nlat@double) then
!       dlat      = new ( 1, "double" )
!   else
!       dlat      = new ( 1, "float" )
!   end if
!   delete (dlat@_FillValue)
!
!   dlat          = 180./(nlat-1)              ; output lat
!   lat           = ispan ( 0,nlat-1,1 )*dlat - 90.
!   lat!0         = dimName
!   lat@long_name = longName
!   lat@units     = units
!   lat&$dimName$ = lat
!   return (lat)
! end
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_latGlobeFo(nlat, ylat)
!
!   INTEGER, INTENT(IN   ) :: nlat
!   REAL,    INTENT(  OUT) :: ylat(nlat)
!
!---------------------------------------
!
! D. Shea
! Generate latitudes for a Fixed-Offset global grid
! Example: nlat= 72
!          lat = latGlobeFo (nlat, "lat", "latitude", "degrees_north")
!          lat will run from -> -87.5 to 87.5 in the above example
!
! set nlat@double = True if double precision is desired
!
! undef ("latGlobeFo")
! function latGlobeFo(nlat:integer,dimName:string,longName:string,units:string)
! local dlat, offset, lat
! begin
!   if (isatt(nlat,"double") .and. nlat@double) then
!       dlat      = new ( 1, "double" )
!   else
!       dlat      = new ( 1, "float" )
!   end if
!   delete (dlat@_FillValue)
!
!   dlat          = 180./nlat           ; output lat
!   offset        = dlat*0.5
!   lat           = ispan ( 0,nlat-1,1 )*dlat - 90. + offset
!   lat!0         = dimName
!   lat@long_name = longName
!   lat@units     = units
!   lat&$dimName$ = lat
!   return (lat)
! end
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_latGau(nlat, ylat)
!
!   INTEGER, INTENT(IN   ) :: nlat
!   REAL,    INTENT(  OUT) :: ylat(nlat)
!
!---------------------------------------
!
! D. Shea
! Generate gaussian latitudes and meta data
! nlat = 64
! lat  = latGau (nlat, "lat", "latitude", "degrees_north")
!
! set nlat@double = True if double precision is desired
!
! undef ("latGau")
! function latGau (nlat:integer, dimName:string, longName:string, units:string)
! local gau_info, lat
! begin
!   if (isatt(nlat,"double") .and. nlat@double) then
!       gau_info  = gaus(nlat/2)
!   else
!       gau_info  = doubletofloat(gaus(nlat/2))
!   end if
!
!   lat           = gau_info(:,0)       ; lat values
!   lat!0         = dimName             ; name the dimension
!   lat@long_name = longName
!   lat@units     = units
!   lat&$dimName$ = lat                 ; coordinate variable
!   return (lat)
! end
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_latGau2(nlat, ylat, ywgt)
!
!   INTEGER, INTENT(IN   ) :: nlat
!   REAL,    INTENT(  OUT) :: ylat(nlat), ywgt(nlat)
!
! Routine to Generate gaussian latitudes and gaussian weights
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_latGauWgt(nlat, ywgt)
!
!   INTEGER, INTENT(IN   ) :: nlat
!   REAL,    INTENT(  OUT) :: ywgt(nlat)
!
!---------------------------------------
!
! D. Shea
! Generate gaussian weights and meta data
! nlat = 64
! gwt  = latGauWgt (nlat, "lat", "gaussian weights", "dimension_less")
! gwt  = latGauWgt (nlat, "lat", "gaussian weights", "")
!
! set nlat@double = True if double precision is desired
!
! undef ("latGauWgt")
! function latGauWgt(nlat:integer,dimName:string,longName:string,units:string)
! local gau_info, gwt
! begin
!   if (isatt(nlat,"double") .and. nlat@double) then
!       gau_info  = gaus(nlat/2)
!   else
!       gau_info  = doubletofloat(gaus(nlat/2))
!   end if
!
!   gwt           = gau_info(:,1)       ; gaussian wgt values
!   gwt!0         = dimName             ; name the dimension
!   gwt@long_name = longName
!   if (units.ne."")then
!       gwt@units     = units
!   end if
!   gwt&$dimName$ = gau_info(:,0)       ; lat to named dimension
!   return (gwt)
! end
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_latRegWgt(nlat, ylat, ywgt, iopt)
!
!   INTEGER, INTENT(IN   ) :: nlat
!   REAL,    INTENT(IN   ) :: ylat(nlat)
!   REAL,    INTENT(  OUT) :: ywgt(nlat)
!   INTEGER, INTENT(IN   ) :: iopt
!
!---------------------------------------
!
! D. Shea
! Generate [sin(lat+dlat/2)-sin(lat-dlat/2)] weights
! for equally spaced grids. Currently, only global grids are supported.
!
! undef("latRegWgt")
! function latRegWgt(lat[*]:numeric, nType[1]:string, opt[1]:integer)
! ; usage: wgt = latRegWgt(lat, "double", 0)
! ;        wgt = latRegWgt(lat, "float" , 0)
! local nlat, pi, rad, err, eps, dlat, dlat_low, dlat_hgh, diff, nl, dNam
! begin
!   nlat = dimsizes(lat)
!   pi   = 4.0d*atan(1.0d)
!   rad  = pi/180.0d
!   err  = 1d20
!   eps  = 0.001                          ; arbitrary
!
!   dlat = abs(lat(2)-lat(1))             ; error check
!   dlat_low = dlat-eps
!   dlat_hgh = dlat+eps
!   diff     = all(abs(lat(1:nlat-1)-lat(0:nlat-2)) .ge. dlat_low) .and. \
!              all(abs(lat(1:nlat-1)-lat(0:nlat-2)) .le. dlat_hgh)
!   if (.not.diff) then
!       print("latRegWgt: Expecting equally spaced latitudes")
!       if (nType.eq."double") then
!           return(new(nlat,"double",err))
!       else
!           return(new(nlat,"float",doubletofloat(err)))
!       end if
!   end if
!   delete(dlat)
!
!   dlat = abs((lat(2)-lat(1))*rad)*0.5d
!
!   w    = new (nlat, "double", "No_FillValue")
!
!   do nl=0,nlat-1
!      w(nl) = abs( sin(lat(nl)*rad+dlat) - sin(lat(nl)*rad-dlat))
!   end do
!                                         ; poles
!   if (abs(lat(0)).gt.89.9999d) then
!       nl = 0
!     ;;w(nl) = abs( sin(lat(nl)*rad)- sin(lat(nl)*rad-dlat))
!     ;;weight_pole = abs ( 1. - sin(pi/2 - (Delta_phi)/2 )  ; CJ
!       w(nl) = abs ( 1d0 - sin(pi/2d0 - dlat))  ; CJ
!   end if
!   if (abs(lat(nlat-1)).gt.89.9999d) then
!       nl = nlat-1
!     ;;w(nl) = abs( sin(lat(nl)*rad)- sin(lat(nl)*rad-dlat))
!     ;;weight_pole = abs ( 1. - sin(pi/2 - (Delta_phi)/2 )  ; CJ
!       w(nl) = abs ( 1d0 - sin(pi/2d0 - dlat))  ; CJ
!   end if
!
!   dNam = getvardims( lat )
!   if (.not.ismissing(dNam)) then
!       w!0 = dNam
!       if (iscoord(lat, dNam)) then
!           w&$dNam$ = lat
!       end if
!   end if
!   w@long_name = "latitude weight"
!
!   if (nType.eq."double") then
!       return( w )
!   else
!       return(dble2flt(w))
!   end if
! end
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_lonFlip(nlon, m, xlon, varb)
!
!   INTEGER, INTENT(IN   ) :: nlon, m
!   REAL,    INTENT(INOUT) :: xlon(nlon), varb(nlon,m)
!
! Routine to reorder [flip] the longitude coordinate/variable about
! the mid point.
!
! Note: grid must be "global" [no cyclic point] and it assumes that
! the first dimension of "varb" is a coordinate variable corresponding
! to longitude.
!
! Variables:
!
! nlon - longitude dimension, first dimension of array varb
!
! m    - non-longitude dimension, second dimension of array varb
!
! xlon - longitude coordinates array
!
! varb - a two dimensional array with "longitude" as first dimension
!
!---------
!
! Special cases: rank of array "varb" less than 2 or greater than 2
!
!   REAL :: xlon(nlon)
!   REAL :: varb1(nlon), varb4(nlon,nlat,nlev,ntim)
!
!   CALL ng_lonFlip(nlon,              1, xlon, varb1)
!   CALL ng_lonFlip(nlon, nlat*nlev*ntim, xlon, varb4)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_lonPivot(nlon, m, pivotLon, xlon, varb)
!
!   INTEGER, INTENT(IN   ) :: nlon, m
!   REAL,    INTENT(IN   ) :: pivotLon
!   REAL,    INTENT(INOUT) :: xlon(nlon), varb(nlon,m)
!
! Routine to pivot (flip) the contents of coordinate array "xlon" and
! variable array "varb" about some arbitrary user specified longitude.
! The effect is similar to "ng_lonFlip"; However, ng_lonFlip will pivot
! about the mid point [whatever that is]; while thus routine allows the
! user to specify what lon to pivot about.
!
! grid must be "global" [no cyclic point] and it assumes that the
! rightmost dimension of "x" is a coordinate variable corresponding
! to longitude.
!
! Variables:
!
! nlon - longitude dimension, first dimension of array varb
!
! m    - non-longitude dimension, second dimension of array varb
!
! pivotLon - user specified longitude to pivot
!
! xlon - longitude coordinates array
!
! varb - a two dimensional array with "longitude" as first dimension
!
!---------
!
! Special cases: rank of array "varb" less than 2 or greater than 2
!
!   REAL :: xlon(nlon)
!   REAL :: varb1(nlon), varb4(nlon,nlat,nlev,ntim)
!
!   CALL ng_lonPivot(nlon,              1, pivotLon, xlon, varb1)
!   CALL ng_lonPivot(nlon, nlat*nlev*ntim, pivotLon, xlon, varb4)
!
!=====================================================================
! Date and Time
!=====================================================================
!
! SUBROUTINE ng_days_since( days, sinceyear, year, month, day )
! SUBROUTINE ng_hours_since( hours, sinceyear, year, month, day, hour )
!
! REAL FUNCTION ng_yyyymmdd_to_yyyyFrac( yyyymmdd, ddOffset )
! REAL FUNCTION ng_yyyymm_to_yyyyFrac( yyyymm  , mmOffset )
! REAL FUNCTION ng_yyyyddd_to_yyyyFrac( yyyyddd , ddOffset )
!
! INTEGER FUNCTION ng_day_of_weak( Year, Month, Day )
! INTEGER FUNCTION ng_days_in_month( Year, Month )
! INTEGER FUNCTION ng_day_of_year( Year, Month, Day )
! INTEGER FUNCTION ng_monthday( yyyy, ddd )
! LOGICAL FUNCTION ng_isleapyear(Year)
!
! INTEGER  FUNCTION ng_greg2juli( yyyy, mm, dd )     ! convert calendar date to Julian date
! REAL(r8) FUNCTION ng_greg2juld( yyyy, mm, dd, hr )
!
! SUBROUTINE ng_juld2greg( juld, yyyy, mm, dd, hr )  ! expand Julian date into a calendar date
! SUBROUTINE ng_juli2greg( juld, yyyy, mm, dd )
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_days_since( days, sinceyear, year, month, day )
!
!   INTEGER, INTENT(IN   ) :: days, sinceyear
!   INTEGER, INTENT(  OUT) :: year, month, day
!
! Convert a "time" variable (days) with attribute "units", for example,
!   units = "days since 1800-01-01 00:00:00" (sinceyear is 1800, in this case)
! to a UT-referenced date (year, month, and day)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_hours_since( hours, sinceyear, year, month, day, hour )
!
!   INTEGER, INTENT(IN   ) :: hours, sinceyear
!   INTEGER, INTENT(  OUT) :: year, month, day, hour
!
! Convert a "time" variable (hours) with attribute "units", for example,
!   units = "hours since 1800-01-01 00:00:0.0" (sinceyear is 1800, in this case)
! to a UT-referenced date (year, month, day, and hour)
!
!---------------------------------------------------------------------
!
! REAL FUNCTION ng_yyyymmdd_to_yyyyFrac( yyyymmdd, ddOffset )
!
!   INTEGER, INTENT(IN) :: yyyymmdd
!   REAL,    INTENT(IN) :: ddoffset
!
! Convert a "yyyymmdd" value to yyyy and fractional year
!
! dd_offset: A scalar denoting the daily fractional offset.
! A value of zero indicates no daily offset. A value of 0.5
! yields mid-day fractional values. [ 0.0 <= dd_offset < 1.0 ]
!
!---------------------------------------------------------------------
!
! REAL FUNCTION ng_yyyymm_to_yyyyFrac( yyyymm, mmOffset )
!
!   INTEGER, INTENT(IN) :: yyyymm
!   REAL,    INTENT(IN) :: mmoffset
!
! Convert a "yyyymm" value to yyyy and fractional year
!
! mm_offset: A scalar denoting the monthly offset.
! A value of 0.0 yields fractional values starting at 0.0.
! A values of 0.5 yields mid-month fractional values.
!
!---------------------------------------------------------------------
!
! REAL FUNCTION ng_yyyyddd_to_yyyyFrac( yyyyddd, ddOffset )
!
!   INTEGER, INTENT(IN) :: yyyyddd
!   REAL,    INTENT(IN) :: ddoffset
!
! Convert a "yyyyddd" value to yyyy and fractional year
!
! dd_offset: A scalar denoting the daily fractional offset.
! A value of zero indicates no daily offset. A value of 0.5
! yields mid-day fractional values. [ 0.0 <= dd_offset < 1.0 ]
!
!---------------------------------------------------------------------
!
! INTEGER FUNCTION ng_day_of_week( Year, Month, Day )
!
!   INTEGER, INTENT(IN) :: Year, Month, Day
!
! Calculates the day of the week given month, day, and year (Gregorian
! calendar). A integer with value between 0 and 6, where 0=Sunday,
! 1=Monday, ..., 6=Saturday.
!
!---------------------------------------------------------------------
!
! INTEGER FUNCTION ng_days_in_month( Year, Month )
!
!   INTEGER, INTENT(IN) :: Year, Month
!
! Calculates the number of days in a month given month and year.
!
!---------------------------------------------------------------------
!
! INTEGER FUNCTION ng_day_of_year( Year, Month, Day )
!
!   INTEGER, INTENT(IN) :: Year, Month, Day
!
! Calculates the day of the year (sometimes erroneously referred to
! as 'julian day') given Gregorian calendar month, day, and year.
!
!---------------------------------------------------------------------
!
! INTEGER FUNCTION ng_monthday( yyyy, ddd )
!
!   INTEGER, INTENT(IN) :: yyyy, ddd
!
! Function to calculate a concatenated month_day (format mmdd) given
! a day (ddd) and year (yyyy).
!
!---------------------------------------------------------------------
!
! LOGICAL FUNCTION ng_isleapyear(Year)
!
!   INTEGER, INTENT(IN) :: Year
!
! Determines if a given year is a leap year.
!
!---------------------------------------------------------------------
!
! INTEGER FUNCTION ng_greg2juli( yyyy, mm, dd )
!
!   INTEGER, INTENT(IN) :: yyyy, mm, dd
!
! converts calendar date to Julian date
! .   cf Fliegel & Van Flandern, CACM 11(10):657, 1968
!
! nomenclature:
! .   yyyy   - year
! .   mm     - month [1 to 12]
! .   dd     - day   [1 to 31]
!
! A Julian day is defined as the number of days
! .   since January 1, 4713 B.C.
! A Julian day begins at noon Universal Time [UT; 12Z]
! .   of the given date.
!
! Examples:
! .   integer gregjuli,  julday
! .   julday = ng_greg2juli (1900,1,1)   ==>  julday=2415021
!
!---------------------------------------------------------------------
!
! FUNCTION ng_greg2juld( yyyy, mm, dd, hr )
!
!   INTEGER, PARAMETER :: r8=SELECTED_REAL_KIND(p=15)
!   REAL(r8) :: greg2juld
!   INTEGER, INTENT(IN) :: yyyy, mm, dd, hr
!
! converts calendar date to Julian date
! .   cf Fliegel & Van Flandern, CACM 11(10):657, 1968
! .   =====> minor modifications by Shea <=====
!
! nomenclature:
! .   yyyy   - year
! .   mm     - month [1 to 12]
! .   dd     - day   [1 to 31]
! .   hr     - hour  [0 =< hour <= 23]
!
! A Julian day is defined as the number of days
! .   since January 1, 4713 B.C.
! A Julian day begins at noon Universal Time [UT; 12Z]
! .   of the given date.
!
! Examples:
! .   real julday
! .   julday = ng_greg2juld (1900,1,1,0)    ==>  julday=2415020.5
! .   julday = ng_greg2juld (1900,1,1,3)    ==>  julday=2415020.625
! .   julday = ng_greg2juld (1900,1,1,6)    ==>  julday=2415020.75
! .   julday = ng_greg2juld (1900,1,1,12)   ==>  julday=2415021.
! .   julday = ng_greg2juld (1900,1,1,15)   ==>  julday=2415021.125
! .   julday = ng_greg2juld (1900,1,1,18)   ==>  julday=2415021.25
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_juld2greg( juld, yyyy, mm, dd, hr )
!
!   INTEGER, PARAMETER :: r8=SELECTED_REAL_KIND(p=15)
!   REAL(r8), INTENT(IN   ) :: juld
!   INTEGER,  INTENT(  OUT) :: yyyy, mm, dd, hr
!
! expands a Julian date into a calendar date
! cf Fliegel & Van Flandern, CACM 11(10):657, 1968
! .   =====> minor modifications by Shea <=====
!
! A Julian day is defined as the number of days
! .   since January 1, 4713 B.C.
! A Julian day begins at noon Universal Time [UT; 12Z]
! .   of the given date.
!
! Examples:
! .   call ng_juld2greg (2415020.5 ,yyyy,mm,dd,hr) ==> 1900,1,1,0
! .   call ng_juld2greg (2415020.75,yyyy,mm,dd,hr) ==> 1900,1,1,6
! .   call ng_juld2greg (2415021.  ,yyyy,mm,dd,hr) ==> 1900,1,1,12
! .   call ng_juld2greg (2415021.25,yyyy,mm,dd,hr) ==> 1900,1,1,18
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_juli2greg( juld, yyyy, mm, dd )
!
!   INTEGER, INTENT(IN   ) :: juld
!   INTEGER, INTENT(  OUT) :: yyyy, mm, dd
!
! expands a Julian date into a calendar date
! cf Fliegel & Van Flandern, CACM 11(10):657, 1968
! .   =====> minor modifications by Shea <=====
!
! A Julian day is defined as the number of days
! .   since January 1, 4713 B.C.
! A Julian day begins at noon Universal Time [UT; 12Z]
! .   of the given date.
!
! Examples:
! .   call ng_juli2greg (2415021,nyear,nmo,ndy,nhr) ==> 1900,1,1,12
!
!=====================================================================
! Local Min/Max, Area/Volume Average
!=====================================================================
!
! SUBROUTINE ng_local_min(ni, nj, x, xmsg, cyclic, delta, ninj, xi, yj, locmin, nmin)
!
! SUBROUTINE ng_local_max(ni, nj, x, xmsg, cyclic, delta, ninj, xi, yj, locmax, nmax)
!
! SUBROUTINE ng_wgt_areaave(mx, ny, wgtx, wgty, t, tmsg, iflag, ave)
!
! SUBROUTINE ng_wgt_volave    (mx, ny, kz, wgtx, wgty, wgtz, t, tmsg, iflag, ave)
! SUBROUTINE ng_wgt_volave_ccm(mx, ny, kz, wgtx, wgty, wgtz, t, tmsg, iflag, ave)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_local_min(ni, nj, x, xmsg, cyclic, delta, ninj, xi, yj, locmin, nmin)
!
!   INTEGER, INTENT(IN   ) :: ni, nj
!   REAL,    INTENT(IN   ) :: x(ni,nj), xmsg
!   LOGICAL, INTENT(IN   ) :: cyclic
!   REAL,    INTENT(IN   ) :: delta
!   INTEGER, INTENT(IN   ) :: ninj
!   INTEGER, INTENT(  OUT) :: xi(ninj), yj(ninj)
!   REAL,    INTENT(  OUT) :: locmin(ninj)
!   INTEGER, INTENT(  OUT) :: nmin
!
! Routine to calculate the local minima. It returns the x and y
! indices of the minima location, and the minima values.
!
! Variables:
!
!   ni     - dimension size ["x-axis": eg longitude]
!
!   nj     - dimension size ["y-axis": eg latitude ]
!
!   x      - 2-d input/output array
!
!   xmsg   - value of missing points
!
!   cyclic - flag
!            = .TRUE.,  data are cyclic in x
!            = .FALSE., data are not cyclic
!
!   delta  - surrounding points must be different from the
!            central value to be considered a local minimum
!            Normally: delta = 0.0
!
!   ninj   - max number of points  (ni*nj is overkill but safe)
!
!   xi     - x-axis coordinates [eg, longitudes]
!            The fortran subscripts have been adjusted for NCL
!
!   yj     - y-axis coordinates [eg, latitudes ]
!            The fortran subscripts have been adjusted for NCL
!
!   locmin - 1D array dimensioned (ninj), the calculated minimum values
!
!   nmin   - actual number of local minima detected
!
! notes:
!
!      1)  if a point or any of its neighbors is missing, check is
!          not implemented
!      2)  this routine does not check the edges, just the interior
!          except when "cyclic" is true.
!      3)  array has to have at least 3 points in each direction
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_local_max(ni, nj, x, xmsg, cyclic, delta, ninj, xi, yj, locmax, nmax)
!
!   INTEGER, INTENT(IN   ) :: ni, nj
!   REAL,    INTENT(IN   ) :: x(ni,nj), xmsg
!   LOGICAL, INTENT(IN   ) :: cyclic
!   REAL,    INTENT(IN   ) :: delta
!   INTEGER, INTENT(IN   ) :: ninj
!   INTEGER, INTENT(  OUT) :: xi(ninj), yj(ninj)
!   REAL,    INTENT(  OUT) :: locmax(ninj)
!   INTEGER, INTENT(  OUT) :: nmax
!
! Routine to calculate the local maxima. It returns the x and y
! indices of the maxima location, and the maxima values.
!
! Variables:
!
!   ni     - dimension size ["x-axis": eg longitude]
!
!   nj     - dimension size ["y-axis": eg latitude ]
!
!   x      - 2-d input/output array
!
!   xmsg   - value of missing points
!
!   cyclic - flag
!            = .TRUE.,  data are cyclic in x
!            = .FALSE., data are not cyclic
!
!   delta  - surrounding points must be different from the
!            central value to be considered a local maximum
!            Normally: delta = 0.0
!
!   ninj   - max number of points  (ni*nj is overkill but safe)
!
!   xi     - x-axis coordinates [eg, longitudes]
!            The fortran subscripts have been adjusted for NCL
!
!   yj     - y-axis coordinates [eg, latitudes ]
!            The fortran subscripts have been adjusted for NCL
!
!   locmax - 1D array dimensioned (ninj), the calculated maximum values
!
!   nmax   - actual number of local maxima detected
!
! notes:
!
!      1)  if a point or any of its neighbors is missing, check is
!          not implemented
!      2)  this routine does not check the edges, just the interior
!          except when "cyclic" is true.
!      3)  array has to have at least 3 points in each direction
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_wgt_areaave(mx, ny, wgtx, wgty, t, tmsg, iflag, ave)
!
!   INTEGER, INTENT(IN   ) :: mx, ny
!   REAL,    INTENT(IN   ) :: wgtx(mx), wgty(ny)
!   REAL,    INTENT(IN   ) :: t(mx,ny), tmsg
!   INTEGER, INTENT(IN   ) :: iflag
!   REAL,    INTENT(  OUT) :: ave
!
! compute the weighted area average
!
! Nomenclature:
!
! INPUT:
!   mx     - 1st [faster varying] dimension of "t" [eg, longitude]
!   ny     - 2nd [slower varying] dimension of "t" [eg, latitude ]
!   wgtx   - 1D array of length "mx"
!   wgty   - 1D array of length "ny" [eg: cos(0.01745*lat) or gau_wgt(:)]
!   t      - 2D array
!   tmsg   - msg value
!   iflag  - flag
!            =0 compute  average ignoring msg values
!            =1 if any msg data is encountered return as msg
!
! OUTPUT:
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_wgt_volave(mx, ny, kz, wgtx, wgty, wgtz, t, tmsg, iflag, ave)
!
!   INTEGER, INTENT(IN   ) :: mx, ny, kz
!   REAL,    INTENT(IN   ) :: wgtx(mx), wgty(ny), wgtz(kz)
!   REAL,    INTENT(IN   ) :: t(mx,ny,kz), tmsg
!   INTEGER, INTENT(IN   ) :: iflag
!   REAL,    INTENT(  OUT) :: ave
!
! compute the weighted volume average
! .   This could have been programmed more efficiently.
!
! Nomenclature:
!
! INPUT:
!   mx     - 1st [fastest varying] dimension of "t" [eg, longitude]
!   ny     - 2nd [slower  varying] dimension of "t" [eg, latitude ]
!   kz     - 3rd [slowest varying] dimension of "t" [eg, level ]
!   wgtx   - 1D array of length "mx"
!   wgty   - 1D array of length "ny"
!   wgtz   - 1D array of length "kz"
!   t      - 3D array
!   tmsg   - msg value
!   iflag  - flag
!            =0 compute average ignoring msg values
!            =1 if any msg data is encountered return as msg
!
! OUTPUT:
!   ave    - volume average [returned]
!
! Note: I could do this in one loop but I did it this way for
! .     consistency with some other subroutines (wgt_volave_ccm).
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_wgt_volave_ccm(mx, ny, kz, wgtx, wgty, wgtz, t, tmsg, iflag, ave)
!
!   INTEGER, INTENT(IN   ) :: mx, ny, kz
!   REAL,    INTENT(IN   ) :: wgtx(mx), wgty(ny), wgtz(mx,ny,kz)
!   REAL,    INTENT(IN   ) :: t(mx,ny,kz), tmsg
!   INTEGER, INTENT(IN   ) :: iflag
!   REAL,    INTENT(  OUT) :: ave
!
! compute the weighted volume average
! .   This could have been programmed more efficiently.
!
! Nomenclature:
!
! INPUT:
!   mx     - 1st [fastest varying] dimension of "t" [eg, longitude]
!   ny     - 2nd [slower  varying] dimension of "t" [eg, latitude ]
!   kz     - 3rd [slowest varying] dimension of "t" [eg, level ]
!   wgtx   - 1D array of length "mx"
!   wgty   - 1D array of length "ny"
!   wgtz   - 3D array [same size as "t"]. This is really designed for "delta p"
!   t      - 3D array
!   tmsg   - msg value
!   iflag  - flag
!            =0 compute average ignoring msg values
!            =1 if any msg data is encountered return as msg
!
! OUTPUT:
!   ave    - volume average [returned]
!
!=====================================================================
! ReGrid and Interpolation
!=====================================================================
!
! SUBROUTINE ng_linint1(nxi, xi, fi, xmsg, icycx, iopt, nxo, xo, fo, ier)
! SUBROUTINE ng_linint2(nxi, nyi, xi, yi, fi, xmsg, icycx, iopt, nxo, nyo, xo, yo, fo, ier)
! SUBROUTINE ng_linint2_points(nxi, nyi, xi, yi, fi, xmsg, icycx, nxyo, xo, yo, fo, ier)
!
! SUBROUTINE ng_f2fsh(nlona, nlata, aa, nlonb, nlatb, bb)
! SUBROUTINE ng_f2gsh(nlona, nlata, aa, twave, nlonb, nlatb, bb)
! SUBROUTINE ng_g2fsh(nlona, nlata, aa, nlonb, nlatb, bb)
! SUBROUTINE ng_g2gsh(nlona, nlata, aa, twave, nlonb, nlatb, bb)
!
! SUBROUTINE ng_int2p(npin, ppin, xxin, xmsg, linlog, npout, ppout, xxout, ier)
! SUBROUTINE ng_sigma2hybrid(nlvi, sigi, dati, psfc, p0, intyp, nlvo, hya, hyb, sigo, dato)
!
! SUBROUTINE ng_area_conserve_remap   (plon, plat, plono, plato, plev,&
!                                      clon, clat, clono, clato, xx, xxmsg,&
!                                      nlat, nlato, bin_factor, yy)
! SUBROUTINE ng_area_conserve_remap_r4(plon, plat, plono, plato, plev,&
!                                      clon, clat, clono, clato, xx, xxmsg,&
!                                      nlat, nlato, bin_factor, yy)
!
! SUBROUTINE ng_poisson_grid_fill(xio, mx, ny, xmsg, is_cyclic, guess_type, nscan, epsx, relc, iopt)
!
! SUBROUTINE ng_area_hi2lores(mxi, nyi, xi, yi, zi, zimsg, icyc, wyi, mxo, nyo, xo, yo, zo, critpc)
!
! SUBROUTINE ng_triple2grid(kz, xi, yi, zi, zmsg, mx, ny, gx, gy, grid, ier)
!
! SUBROUTINE ng_obj_anal_ic(npts, xlon, ylat, zval, xymsg, zmsg, nscan, rscan, blend, nlon, nlat, glon, glat, gval, ier)
!
! SUBROUTINE ng_bin_sum(nz, zlon, zlat, zval, zmsg, nlon, nlat, glon, glat, gbin, gknt)
! SUBROUTINE ng_bin_avg(nz, zlon, zlat, zval, zmsg, nlon, nlat, glon, glat, gbinknt, ier)
!
! SUBROUTINE ng_smth9    (ni, nj, xi, xmsg, p, q, lwrap, xo)
! SUBROUTINE ng_smooth92d(nx, ny, zi, p, q, zo)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_linint1(nxi, xi, fi, xmsg, icycx, iopt, nxo, xo, fo, ier)
!
!   INTEGER, INTENT(IN   ) :: nxi
!   REAL,    INTENT(IN   ) :: xi(nxi)
!   REAL,    INTENT(IN   ) :: fi(nxi), xmsg
!   INTEGER, INTENT(IN   ) :: icycx, iopt
!   INTEGER, INTENT(IN   ) :: nxo
!   REAL,    INTENT(IN   ) :: xo(nxo)
!   REAL,    INTENT(  OUT) :: fo(nxo)
!   INTEGER, INTENT(  OUT) :: ier
!
! Routine to perform piecewise linear interpolation allowing for
! missing data
!
! Variables:
!
!   nxi   - lengths of xi and dimensions of fi (must be >= 2)
!
!   xi    - coordinates of fi (eg, lon)
!           must be monotonically (in/de)creasing [same as xo]
!
!   fi    - functional input values [2D]
!
!   xmsg  - missing code of fi
!
!   icycx - 0 if fi is not cyclic in x
!           .ne.0 if cyclic (cyclic pt should NOT included)
!
!   iopt  - options
!         - iopt=0  means to try to preserve missing areas
!         - iopt=1  means to try to try to fill-in missing areas
!
!   nxo   - lengths of xo and dimensions of fo (must be >= 1)
!
!   xo    - coordinates of fo (eg, lon)
!           must be monotonically (in/de)creasing [same as xi]
!
!   fo    - functional output values [interpolated]
!
!   ier   - error code
!           =0;  no error
!           =1;  not enough points in input/output array
!           =2;  xi are not monotonically increasing
!           =4;  xo are not monotonically increasing
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_linint2(nxi, nyi, xi, yi, fi, xmsg, icycx, iopt, nxo, nyo, xo, yo, fo, ier)
!
!   INTEGER, INTENT(IN   ) :: nxi, nyi
!   REAL,    INTENT(IN   ) :: xi(nxi), yi(nyi)
!   REAL,    INTENT(IN   ) :: fi(nxi,nyi), xmsg
!   INTEGER, INTENT(IN   ) :: icycx, iopt
!   INTEGER, INTENT(IN   ) :: nxo, nyo
!   REAL,    INTENT(IN   ) :: xo(nxo), yo(nyo)
!   REAL,    INTENT(  OUT) :: fo(nxo,nyo)
!   INTEGER, INTENT(  OUT) :: ier
!
! Routine to perform bilinear interpolation allowing for missing data
!
! Variables:
!
!   nxi,nyi - lengths of xi,yi and dimensions of fi (must be >= 2)
!
!   xi      - coordinates of fi (eg, lon)
!             must be monotonically increasing
!
!   yi      - coordinates of fi (eg, lat)
!             must be monotonically increasing
!
!   fi      - functional input values [2D]
!
!   xmsg    - missing code of fi
!
!   icycx   - 0 if fi is not cyclic in x
!             .ne.0 if cyclic (cyclic pt should NOT included)
!
!   iopt    - =0 try to preserve msg areas
!             =1 try to fill in entire grid
!
!   nxo,nyo - lengths of xo,yo and dimensions of fo (must be >= 2)
!
!   xo      - coordinates of fo (eg, lon)
!             must be monotonically increasing
!
!   yo      - coordinates of fo (eg, lat)
!             must be monotonically increasing
!
!   fo      - functional output values [interpolated]
!
!   ier     - error code
!             =0;  no error
!             =1;  not enough points in input/output array
!             =2;  xi or xo are not monotonically (in/de)creasing
!             =3;  yi or yo are not monotonically (in/de)creasing
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_linint2_points(nxi, nyi, xi, yi, fi, xmsg, icycx, nxyo, xo, yo, fo, ier)
!
!   INTEGER, INTENT(IN   ) :: nxi, nyi
!   REAL,    INTENT(IN   ) :: xi(nxi), yi(nyi)
!   REAL,    INTENT(IN   ) :: fi(nxi,nyi), xmsg
!   INTEGER, INTENT(IN   ) :: icycx
!   INTEGER, INTENT(IN   ) :: nxyo
!   REAL,    INTENT(IN   ) :: xo(nxyo), yo(nxyo)
!   REAL,    INTENT(  OUT) :: fo(nxyo)
!   INTEGER, INTENT(  OUT) :: ier
!
! Routine to perform 2D piecewise linear interpolation allowing for
! missing data
!
! Variables:
!
!   nxi,nyi - lengths of xi,yi and dimensions of fi (must be >= 2)
!
!   xi      - coordinates of fi (eg, lon)
!             must be monotonically increasing
!
!   yi      - coordinates of fi (eg, lat)
!             must be monotonically increasing
!
!   fi      - functional input values [2D]
!
!   xmsg    - missing code of fi
!
!   icycx   - 0 if fi is not cyclic in x (cyclic pt should NOT included)
!             .ne.0 if cyclic (cyclic pt should NOT included)
!
!   nxyo    - number of xo,yo coordinate pairs
!
!   xo,yo   - coordinate pairs
!
!   fo      - functional output values [interpolated]
!
!   ier     - error code
!             =0;   no error
!             =1;   not enough points in input/output array
!             =2/3; xi or yi are not monotonically increasing
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_f2fsh(nlona, nlata, aa, nlonb, nlatb, bb)
!   IMPLICIT NONE
!   INTEGER, INTENT(IN   ) :: nlona, nlata
!   REAL,    INTENT(IN   ) :: aa(nlona,nlata)
!   INTEGER, INTENT(IN   ) :: nlonb, nlatb
!   REAL,    INTENT(  OUT) :: bb(nlonb,nlatb)
!
! Routine to interpolate a scalar quantity from one fixed grid to
! another using spherical harmonics (via the Spherepack code).
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_f2gsh(nlona, nlata, aa, twave, nlonb, nlatb, bb)
!
!   INTEGER, INTENT(IN   ) :: nlona, nlata
!   REAL,    INTENT(IN   ) :: aa(nlona,nlata)
!   INTEGER, INTENT(IN   ) :: twave
!   INTEGER, INTENT(IN   ) :: nlonb, nlatb
!   REAL,    INTENT(  OUT) :: bb(nlonb,nlatb)
!
! Routine to interpolate a scalar quantity from a fixed grid to a
! Gaussian grid (with optional truncation) using spherical harmonics
! (via the Spherepack code).
!
!   twave - indicating the optional wave truncation:
!
!           = 0 => exact interpolation
!
!           > 0 => exact interpolation and triangular truncation at
!                  twave
!
!           < 0 => exact interpolation, triangular truncation at twave
!                  and spectral coefficient tapering (the effect is to
!                  smooth the data)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_g2fsh(nlona, nlata, aa, nlonb, nlatb, bb)
!
!   INTEGER, INTENT(IN   ) :: nlona, nlata
!   REAL,    INTENT(IN   ) :: aa(nlona,nlata)
!   INTEGER, INTENT(IN   ) :: nlonb, nlatb
!   REAL,    INTENT(  OUT) :: bb(nlonb,nlatb)
!
! Routine to interpolate a scalar quantity on a Gaussian grid to a
! fixed grid using spherical harmonics (via the Spherepack code).
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_g2gsh(nlona, nlata, aa, twave, nlonb, nlatb, bb)
!
!   INTEGER, INTENT(IN   ) :: nlona, nlata
!   REAL,    INTENT(IN   ) :: aa(nlona,nlata)
!   INTEGER, INTENT(IN   ) :: twave
!   INTEGER, INTENT(IN   ) :: nlonb, nlatb
!   REAL,    INTENT(  OUT) :: bb(nlonb,nlatb)
!
! Routine to interpolate a scalar quantity from one Gaussian grid to
! another (with optional truncation) using spherical harmonics (via
! the Spherepack code).
!
!   twave - indicating the optional wave truncation:
!
!           = 0 => exact interpolation
!
!           > 0 => exact interpolation and triangular truncation at
!                  twave
!
!           < 0 => exact interpolation, triangular truncation at twave
!                  and spectral coefficient tapering (the effect is to
!                  smooth the data)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_int2p(npin, ppin, xxin, xmsg, linlog, npout, ppout, xxout, ier)
!
!   INTEGER, INTENT(IN   ) :: npin
!   REAL,    INTENT(IN   ) :: ppin(npin), xxin(npin), xmsg
!   INTEGER, INTENT(IN   ) :: linlog
!   INTEGER, INTENT(IN   ) :: npout
!   REAL,    INTENT(INOUT) :: ppout(npout) ! possibly reverse to original order (v640)
!   REAL,    INTENT(  OUT) :: xxout(npout)
!   INTEGER, INTENT(  OUT) :: ier
!
! Routine to interpolate from one set of pressure levels to another set
! using linear or ln(p) interpolation
!
! Variables:
!
! npin   - number of input pressure levels >= 2
!
! ppin   - input pressure levels. The pin can be
!          be in ascending or descending order
!
! xxin   - data at corresponding input pressure levels
!
! xmsg   - missing data code (for ppin/xxin). if none, set to some
!          number which will not be encountered (e.g., 1.e+36)
!
! linlog - if abs(linlog)=1 use linear interp in pressure
!          if abs(linlog) anything but =1 linear interp in
!              ln(pressure)
!          If the value is negative then the routine will
!          extrapolate. Be wary of results in this case.
!
! npout  - number of output pressure levels
!
! ppout  - output pressure levels (input by user)
!          same (ascending or descending) order as pin
!          *** possibly reverse to original order
!
! xxout  - data at corresponding output pressure levels
!
! ier    - error code
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_sigma2hybrid(nlvi, sigi, dati, psfc, p0, intyp, nlvo, hya, hyb, sigo, dato)
!
!   INTEGER, INTENT(IN   ) :: nlvi
!   REAL,    INTENT(IN   ) :: sigi(nlvi), dati(nlvi)
!   REAL,    INTENT(IN   ) :: psfc, p0
!   INTEGER, INTENT(IN   ) :: intyp
!   INTEGER, INTENT(IN   ) :: nlvo
!   REAL,    INTENT(IN   ) :: hya (nlvo), hyb (nlvo)
!   REAL,    INTENT(  OUT) :: sigo(nlvo), dato(nlvo)
!
! Routine to interploate data to model hybrid coordinates from sigma
! coordinates using sigma surfaces.
!
! Variables:
!
!   nlvi  - size of input data array dati
!
!   sigi  - sigma coordinates of dati, order is top-to-bottom
!
!   dati  - input data array (in sigma coordinates) to be interpolated
!
!   psfc  - surface pressures in Pa
!
!   p0    - surface reference pressure in Pa
!
!   intyp - flag indicating the type of vertical interpolation to be performed
!           1 = linear,
!           2 = log ,
!           3 = log-log
!
!   nlvo  - size of arrays hya, hyb, dato, and sigo
!
!   hya   - the hybrid A coefficients
!
!   hyb   - the hybrid B coefficients
!
!   sigo  - the hybrid coordinates of dato
!
!   dato  - interpolated (output) data array, in hybrid coordinates
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_area_conserve_remap(plon, plat, plono, plato, plev,&
!                                   clon, clat, clono, clato, xx, xxmsg,&
!                                   nlat, nlato, bin_factor, yy)
!
!   INTEGER, INTENT(IN   ) :: plon, plat, plono, plato, plev
!   REAL,    INTENT(IN   ) :: clon (plon ), clat (plat )
!   REAL,    INTENT(IN   ) :: clono(plono), clato(plato)
!   REAL,    INTENT(IN   ) :: xx(plon,plat,plev), xxmsg
!   INTEGER, INTENT(IN   ) :: nlat, nlato
!   REAL,    INTENT(IN   ) :: bin_factor
!   REAL,    INTENT(  OUT) :: yy(plono,plato,plev)
!
! Routine to perform areal conservative remapping from one rectilinear
! grid to another and preserves metadata.
!
! Variables:
!
!  plon  - longitude dimension of input field
!
!  plat  - latitude  dimension of input field
!
!  plono - longitude dimension of output field
!
!  plato - latitude  dimension of output field
!
!  plev  - vertical  dimension of input/output field
!
!  clat  - input  latitude  in degrees, oriented S->N
!
!  clon  - input  longitude in degrees, oriented W->E
!
!  clato - output latitude  in degrees, oriented S->N
!
!  clono - output longitude in degrees, oriented W->E
!
!  xx    - input analysis field
!
!  xxmsg - missing code of xx
!
!  nlat  - number of Global Gaussian (input ) latitudes
!
!  nlato - number of Global Gaussian (output) latitudes
!
!  bin_factor - bin-box area expansion/contraction factor
!               relative to output grid-box area.
!
!  yy    - interpolated (output) field
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_area_conserve_remap_r4(plon, plat, plono, plato, plev,&
!                                      clon, clat, clono, clato, xx, xxmsg,&
!                                      nlat, nlato, bin_factor, yy)
!
!   INTEGER, INTENT(IN   ) :: plon, plat, plono, plato, plev
!   REAL,    INTENT(IN   ) :: clon (plon ), clat (plat )
!   REAL,    INTENT(IN   ) :: clono(plono), clato(plato)
!   REAL,    INTENT(IN   ) :: xx(plon,plat,plev), xxmsg
!   INTEGER, INTENT(IN   ) :: nlat, nlato
!   REAL,    INTENT(IN   ) :: bin_factor
!   REAL,    INTENT(  OUT) :: yy(plono,plato,plev)
!
! Routine to perform areal conservative remapping from one rectilinear
! grid to another and preserves metadata. (single precision version)
!
!-------------------------------------------------------------------
!
! SUBROUTINE ng_poisson_grid_fill(xio, mx, ny, xmsg, is_cyclic, guess_type,  nscan, epsx, relc, iopt)
!
!   INTEGER, INTENT(IN   ) :: mx, ny
!   REAL,    INTENT(INOUT) :: xio(mx,ny)
!   INTEGER, INTENT(IN   ) :: guess_type, nscan, iopt
!   LOGICAL, INTENT(IN   ) :: is_cyclic
!   REAL,    INTENT(IN   ) :: xmsg, epsx, relc
!
! Replaces all missing values in a grid with values derived from
! solving Poisson's equation via relaxation.
!
! The values at non-missing locations are used as boundary
! conditions and are returned unchanged.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_area_hi2lores(mxi, nyi, xi, yi, zi, zimsg, icyc, wyi, mxo, nyo, xo, yo, zo, critpc)
!
!   INTEGER, INTENT(IN   ) :: mxi, nyi
!   REAL,    INTENT(IN   ) :: xi(mxi), yi(nyi), zi(mxi,nyi), zimsg, wyi(nyi)
!   LOGICAL, INTENT(IN   ) :: icyc
!   INTEGER, INTENT(IN   ) :: mxo, nyo
!   REAL,    INTENT(IN   ) :: xo(mxo), yo(nyo)
!   REAL,    INTENT(  OUT) :: zo(mxo,nyo)
!   REAL,    INTENT(IN   ), OPTIONAL :: critpc
!
! Routine to interpolate from high resolution rectilinear grids (zi)
! to low resolution rectilinear grids (zo) using local area averaging.
!
! mxi:    Dimension of 1-d array xi and first dimension of 2-d array zi
!
! nxi:    Dimension of 1-d arrays yi and wyi, and, second dimension of 2-d array zi
!
! xi:     A one-dimensional array that specifies the X coordinates of the zi array.
!         It must be monotonically increasing. It may be unequally spaced.
!         For geo-referenced data, xi is generally the longitude array.
!
! yi:     A one-dimensional array that specifies the Y coordinates of the fi array.
!         This may be a monotonically increasing or decreasing array. It may be
!         unequally spaced. For geo-referenced data, yi is generally the latitude
!         array.
!
! zi:     The high resolution rectilinear grids to be interpolated.
!         An array of two dimensions. The two dimensions must of size mxi x nyi.
!
! zimsg:  Missing value of array zi
!
! icyc:   An option to indicate whether dimension mxi of zi is cyclic.
!         This should be set to .TRUE. only if you have global data,
!         but your longitude values don't quite wrap all the way around the globe.
!         For example, if your longitude values go from, say, -179.75 to 179.75,
!         or 0.5 to 359.5, then you would set this to .TRUE..
!
! wyi:    A one dimensional array containing the weights for the yi coordinate.
!         If no weighting is to be used, set to 1. Otherwise, wy could contain
!         (say) gaussian weights or cosines of the latitude.
!
! mxo:    Dimension of 1-d array xo and first dimension of 2-d array zo
!
! nxo:    Dimension of 1-d array yo and second dimension of 2-d array zo
!
! xo:     A one-dimensional array that specifies the X coordinates of the return array.
!         It must be monotonically increasing, but may be unequally spaced.
!         For geo-referenced data, xo is generally the longitude array.
!
! yo:     A one-dimensional array that specifies the Y coordinates of the return array.
!         It may be monotonically increasing or decreasing. It may be unequally spaced.
!         For geo-referenced data, yo is generally the latitude array.
!
! zo:     The interpolated low resolution rectilinear grids.
!         An array of two dimensions. The two dimensions must of size mxo x nyo.
!
! critpc: The parameter that specifies the percentage of input grid points within the
!         scope of the low resolution grid point that must be present. The default is
!         critpc=100.0 (percent), if argument is not present. This means that if any
!         missing values (zimsg) are encountered the output grid point will be set to
!         zimsg. The user may change the default value, if argument present, to any
!         number [0 to 100]. A value of (say) critpc=70.0 (percent) means that a value
!         will be returned if 70% of the high resolution grid points within the scope
!         of the low resolution grid point are non-missing.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_triple2grid(kz, xi, yi, zi, zmsg, mx, ny, gx, gy, grid, ier)
!
!   INTEGER, INTENT(IN   ) :: kz, mx, ny
!   REAL,    INTENT(IN   ) :: xi(kz), yi(kz), zi(kz), zmsg
!   REAL,    INTENT(IN   ) :: gx(mx), gy(ny)
!   REAL,    INTENT(  OUT) :: grid(mx,ny)
!   INTEGER, INTENT(  OUT) :: ier
!
! Places unstructured (randomly-spaced) data onto the nearest
! locations of a rectilinear grid and retains metadata.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_obj_anal_ic(npts, xlon, ylat, zval, xymsg, zmsg, nscan, rscan,&
!                           blend, nlon, nlat, glon, glat, gval, ier)
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: xlon(npts), ylat(npts), zval(npts), xymsg, zmsg
!   INTEGER, INTENT(IN   ) :: nscan
!   REAL,    INTENT(IN   ) :: rscan(nscan)
!   LOGICAL, INTENT(IN   ) :: blend
!   INTEGER, INTENT(IN   ) :: nlon, nlat
!   REAL,    INTENT(IN   ) :: glon(nlon), glat(nlat)
!   REAL,    INTENT(  OUT) :: gval(nlon,nlat)
!   INTEGER, INTENT(  OUT) :: ier
!
! Routine to perform an iterative improvement type objective analysis
! using an input triplet set (xlon, ylat, zval). For each gridpoint,
! multiple passes of descending radii of influence are used to obtain
! better estimates.
!
! Varibales:
!
!   npts         - size of plon/plat/pval arrays
!
!   xlon         - longitude coordinates of observation in degrees
!                  {-180, 0}<= xlon >=(180, 360}
!
!   ylat         - latitude coordinates of observation in degrees
!                  -90.<= ylat =>90.
!
!   zval         - input observatios array
!
!   xymsg        - missing code for xlon and ylat
!
!   zmsg         - missing code for zval
!
!   nscan        - no. of scans to be performed (length of rscan)
!                  it is recommended that multiple scans be
!                  performed. the max number of scans is currently
!                  10. this may easily be adjusted by changing the
!                  parameter nscmax and changing the length of the
!                  data statement for smwgt. this routine was tested
!                  with nscan=4 : rscan(1,2,3,4)=20.,15.,10.,7.5
!                  rscan(nscan) should be .ge. the grid spacing.
!                  within rscan(1) degrees will be set
!
!   rscan        - scan radii (in degrees)
!                  rscan(1)> rscan(2)> ...>rscan(nscan)
!
!   blend        - blending flag
!                  .TRUE., the iteration will 'blending' previous and current values
!                  .FALSE., not 'blending' the iteration (normal case)
!
!   nlon         - longitude dimension of gval
!
!   nlat         - latitude dimension of gval
!
!   glon         - longitude coords of the gval, must have same range as xlon
!
!   glat         - latitude coords of the gval, must have same range as ylon
!
!   gval         - output array which will hold the interpolated values
!
!   ier          - error code
!
! Note: It is possible that some returned grid points could be _FillValue.
!       If this is not desired, increase the radii of influence.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_bin_sum(nz, zlon, zlat, zval, zmsg, nlon, nlat, glon, glat, gbin, gknt)
!
!   INTEGER, INTENT(IN   ) :: nz
!   REAL,    INTENT(IN   ) :: zlon(nz), zlat(nz)
!   REAL,    INTENT(IN   ) :: zval(nz), zmsg
!   INTEGER, INTENT(IN   ) :: nlon, nlat
!   REAL,    INTENT(IN   ) :: glon(nlon), glat(nlat)
!   REAL,    INTENT(INOUT) :: gbin(nlon,nlat)
!   INTEGER, INTENT(INOUT) :: gknt(nlon,nlat)
!
! Routine to calculate binned sums and counts over multiple invocations
! of the procedure on a rectilinear grid.
!
! Variables:
!
! nz   - Size of the observed data (zval).
!
! zlon - Longitudes of the observational data (zval).
!
! zlat - Latitudes of the observational data (zval).
!
! zval - Values of the observed data.
!
! zmsg - Missing Value of Zval.
!
! nlon - Longitude dimesnsion of gbin and gknt
!
! nlat - Latitude dimesnsion of gbin and gknt
!
! glon - Longitudes of gbin and gknt.
!        These are required to be equally spaced.
!
! glat - Latitudes of gbin and gknt.
!        These must be equally spaced but they do not need to be the
!        same spacing as glon.
!
! gbin - User supplied array which will contain the summed quantities.
!        It is the user's responsibility to initialize the array
!        elements to 0.0.
!
! gknt - User supplied array which will contain the integer counts.
!        This must conform to gbin. It is the user's responsibility to
!        initialize the array elements to integer zero.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_bin_avg(nz, zlon, zlat, zval, zmsg, nlon, nlat, glon, glat, gbinknt, ier)
!
!   INTEGER, INTENT(IN   ) :: nz
!   REAL,    INTENT(IN   ) :: zlon(nz), zlat(nz)
!   REAL,    INTENT(IN   ) :: zval(nz), zmsg
!   INTEGER, INTENT(IN   ) :: nlon, nlat
!   REAL,    INTENT(IN   ) :: glon(nlon), glat(nlat)
!   REAL,    INTENT(  OUT) :: gbinknt(nlon,nlat,2)
!   INTEGER, INTENT(  OUT) :: ier
!
! Routine to calculate gridded binned averages and counts on a
! rectilinear grid using randomly spaced data.
!
! Variables:
!
! nz      - Size of the observed data (zval).
!
! zlon    - Longitudes of the observational data (zval).
!
! zlat    - Latitudes of the observational data (zval).
!
! zval    - Values of the observed data.
!
! zmsg    - Missing Value of Zval.
!
! nlon    - Longitude dimesnsion of the output gbin and gknt
!
! nlat    - Latitude dimesnsion of the output gbin and gknt
!
! glon    - Longitudes of the output grid
!           These are required to be equally spaced.
!
! glat    - Latitudes of the output grid
!           These must be equally spaced but they do not need to be the
!           same spacing as glon.
!
! gbinknt - A rectilinear grid of the size defined by glon and glat.
!           The third dimension will be size two (2) for binned
!           "averages" and "counts" respectively, i.e,,
!
!           gbinknt(i,j,1), the binned averages for grid (glon(i),glat(j))
!           gbinknt(i,j,2), the binned counts   for grid (glon(i),glat(j))
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_smth9(ni, nj, xi, xmsg, p, q, lwrap, xo)
!
!   INTEGER, INTENT(IN   ) :: ni, nj
!   REAL,    INTENT(IN   ) :: xi(ni,nj), xmsg
!   REAL,    INTENT(IN   ) :: p, q
!   LOGICAL, INTENT(IN   ) :: lwrap
!   REAL,    INTENT(  OUT) :: xo(ni,nj)
!
! Routine to do 9-point smoothing using the equation:
!
!   f0 = f0 + (p/4)*(f2+f4+f6+f8-4*f0) + (q/4)*(f1+f3+f5+f7-4*f0)
!
!  where the grid is:
!
!      1-------------8---------------7
!      |             |               |
!      |             |               |
!      |             |               |
!      |             |               |
!      2-------------0---------------6
!      |             |               |
!      |             |               |
!      |             |               |
!      |             |               |
!      3-------------4---------------5
!
! Variables:
!
!   ni    - 1st dimension
!
!   nj    - 2nd dimension
!
!   xi    - 2-d input array
!
!   xmsg  - value of missing points for xi
!
!   p     - first  weight (suggested value of 0.50)
!
!   q     - second weight (suggested value of 0.25)
!
!   lwrap - logical flag to include wraparound points in smoothing
!           if lwrap = .true. , smooth left and right endpoints
!           if lwrap = .false., no smoothing
!
!   xo    - 2-d output array
!
! notes:
!
!      1)  if a point or any of its neighbors is missing, the point is
!          not smoothed
!      2)  this routine does not smooth the edges, just the interior
!          with the exception that the left and right edges are smoothed
!          when "lwrap" is true.
!      3)  array has to have at least 3 points in each direction
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_smooth92d(nx, ny, zi, p, q, zo)
!
!   INTEGER, INTENT(IN   ) :: nx, ny
!   REAL,    INTENT(IN   ) :: zi(nx,ny)
!   REAL,    INTENT(IN   ) :: p, q
!   REAL,    INTENT(  OUT) :: zo(nx,ny)
!
! The functions smth9 and smooth92d are basically identical, except
! that smth9 should run faster, and it has an additional option that
! allows you to indicate whether you want the end points smoothed.
! [smth9]==[smooth92d] for no "missing data" and no "end cycle"
!
!=====================================================================
! Random number
!=====================================================================
!
! SUBROUTINE ng_generate_2d_array(data, m, n, mlow, mhgh, dlow, dhgh, iran)
!
! SUBROUTINE ng_generate_unique_indices( iarray, n )
! SUBROUTINE ng_generate_sample_indices( iarray, n, method )
!
! REAL FUNCTION ng_random_chi    ( df )
! REAL FUNCTION ng_random_gamma  ( a, r )
! REAL FUNCTION ng_random_normal ( av, sd )
! REAL FUNCTION ng_random_uniform( low, high )
! SUBROUTINE ng_random_setallseed( seed1, seed2 )
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_generate_2d_array(DATA, M, N, MLOW, MHGH, DLOW, DHGH, ISEED)
!
! This routine generates a two-dimensional array (DATA, dimensioned
! M by N) of pseudo random numbers using a sum of exponentials. The
! values will fall exactly within the range [DLOW,DHGH] and there
! will be approximately MLOW lows and MHGH highs. This routine is
! especially useful for generating random data for nice 2D graphics.
!
!   INTEGER, INTENT(IN   ) :: M, N
!   REAL,    INTENT(  OUT) :: DATA(M,N)
!   INTEGER, INTENT(IN   ) :: MLOW, MHGH
!   REAL,    INTENT(IN   ) :: DLOW, DHGH
!   INTEGER, INTENT(IN   ) :: ISEED
!
! DATA
! the output two-dimensional array
!
! M, N
! The dimension sizes of DATA.
!
! MLOW, MHGH
! The approximate minimum and maximum number of highs and lows that
! the output data should have. They must be in the range 1 to 25.
! If not, then they will be set to either 1 or 25.
!
! DLOW, DHGH
! The exact minimum and maximum value that the output data should have.
!
! ISEED
! Value from 0 to 100 that represents the seed. If a value outside
! this range is entered, then iseed will be set to 0.
!
!---------------------------------------------------------------------
!
! SUBROUTINE generate_unique_indices( iarray, n )
!
! Routine to generate unique random subscript indices.
!
! Variables:
!
!   INTEGER, INTENT(IN   ) :: n
!   INTEGER, INTENT(  OUT) :: iarray(n)
!
!      n - The number of unique random subscripts to be generated.
!
! iarray - A one dimensional array containing the unique random
!          integer subscripts (indices).
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_generate_sample_indices( iarray, n, method )
!
! Routine to generate indices (subscripts) for resampling:
! with and without replacement.
!
! Variables:
!
!   INTEGER, INTENT(IN   ) :: n
!   INTEGER, INTENT(  OUT) :: iarray(n)
!   INTEGER, INTENT(IN   ) :: method
!
!      n - The number of indices (subscripts) to be generated.
!
! iarray - A one dimensional array containing the the random
!          integer indices (subscripts).
!
! method - type of indices should be generated.
!
!          0: Sample without replacement. These can be used to
!             reshuffle the order. Use when the order of sampling
!             may be important. Statistics like the mean and
!             standard deviation will not be changed.
!
!          1: Sample with replacement. These can be used for (say)
!             bootstrap resampling. Statistics like the mean and
!             standard deviation will be changed.
!
! Note: If method=1, the indicies are set using ng_random_uniform.
! Please read the documentation for ng_random_setallseed. The 'seeds'
! can be manually set via ng_random_setallseed.
!
!---------------------------------------------------------------------
!
! REAL FUNCTION ng_random_chi( df )
!   REAL, INTENT(IN) :: df
!
! Function to generate random numbers using a chi-squared distribution.
!
! df: the degrees of freedom of the chi-square distribution
!     (0, +infinity).
!
!---------------------------------------------------------------------
!
! REAL FUNCTION ng_random_gamma( a, r )
!   REAL, INTENT(IN) :: a, r
!
! Function to generate random numbers using a gamma distribution.
!
! a: location parameter of the gamma distribution.
!
! r: shape parameter of the gamma distribution (> 0.0).
!
!---------------------------------------------------------------------
!
! REAL FUNCTION ng_random_normal( av, sd )
!   REAL, INTENT(IN) :: av, sd
!
! Function to generate random numbers using a normal distribution.
!
! av: mean of the normal distribution.
!
! sd: standard deviation of the normal distribution.
!
!---------------------------------------------------------------------
!
! REAL FUNCTION ng_random_uniform( low, high )
!   REAL, INTENT(IN) :: low, high
!
! Function to generate random numbers using a uniform range distribution.
!
! low:  low bound (exclusive) on real values to be generated.
!
! high: high bound (exclusive) on real values to be generated.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_random_setallseed( iseed1, iseed2 )
!   INTEGER, INTENT(IN) :: iseed1, iseed2
!
! Routine to set initial seeds for random number generators.
!
! iseed1: seed 1, between 1 and 2,147,483,562 (default is 1234567890).
!
! iseed2: seed 2, between 1 and 2,147,483,398 (default is 123456789).
!
! If ng_random_setallseed not invoked, the default values are
! 1234567890 and 123456789 for isseed1 and iseed2 separately.
!
!=====================================================================
! Math and Statistics
!=====================================================================
!
! SUBROUTINE NG_PQSORT(X, N, KFLAG, IPERM) ! Quick sorting
!
! SUBROUTINE ng_sum       (x, npts, xmsg, xsum, nptused)                      ! sum
! SUBROUTINE ng_avg       (x, npts, xmsg, xavg, nptused)                      ! average
! SUBROUTINE ng_stddev    (x, npts, xmsg,  std, nptused)                      ! standard deviation
! SUBROUTINE ng_median    (x, npts, xmsg, xmedian, xmrange, xrange, nptused)  ! median
! SUBROUTINE ng_stat1     (x, npts, xmsg, xmean, nptused)                     ! first moment
! SUBROUTINE ng_stat2     (x, npts, xmsg, xmean, xvar, nptused)               ! first two moments
! SUBROUTINE ng_stat2_trim(x, npts, xmsg, ptrim, xmean, xvar, nptused)        ! trimmed estimates of the first two moments
! SUBROUTINE ng_stat4     (x, npts, xmsg, xmean, xvar, xskew, xkurt, nptused) ! first four moments
!
! SUBROUTINE ng_stat_dispersion(x, npts, xmsg, statx, PrintStat ) ! robust dispersion statistics
!
! SUBROUTINE ng_sum_wgt(x, npts, xmsg, wgt, iopt, xsum) ! weighted sum
! SUBROUTINE ng_avg_wgt(x, npts, xmsg, wgt, iopt, xavg) ! weighted average
!
! SUBROUTINE ng_rmsd(x, y, npts, xmsg, ymsg, xyrmsd)    ! root-mean-square-difference
!
! SUBROUTINE ng_rmvmean    (x, npts, xmsg)       ! remove series mean
! SUBROUTINE ng_rmvmed     (x, npts, xmsg)       ! remove series median
! SUBROUTINE ng_standardize(x, npts, xmsg, iopt) ! remove mean and standardize
!
! SUBROUTINE ng_runave( X, NPTS, NAVE, KOPT, XMSG ) ! unweighted running average
! SUBROUTINE ng_wgt_runave( X, NPTS, WGT, NWGT, KOPT, XMSG ) ! weighted running average
!
! SUBROUTINE ng_filwgt_normal  ( wt, nwt, sigma, itype )                     ! Normal Filter Weights
! SUBROUTINE ng_filwgts_lanczos( wt, nwt, ihp, fca, fcb, sigma, freq, resp ) ! Lanczos Filter Weights
! SUBROUTINE ng_bw_bandpass_filter( x, y, n, fca, fcb, m, dt, mzer, e )      ! Butterworth Bandpass Filter
! SUBROUTINE ng_demod_cmplx(ntim, x, frqdem, frqcut, nwt, opt, xamp, xpha)   ! complex demodulation on a time series
! SUBROUTINE ng_ezfftf( npts, x, xbar, cf ) ! FFT filtering (Fourier analysis)
! SUBROUTINE ng_ezfftb( npts, xbar, cf, x ) ! FFT filtering (Fourier synthesis)
! SUBROUTINE ng_fourier_info( nx, x, nhx, sclPha, finfo ) ! Fourier analysis, returns amplitude, phase, and percent variance
!
! SUBROUTINE ng_regline( x, y, npts, xmsg, ymsg, rcoef, yint, rstd, tval, xave, yave, nptxy ) ! simple linear regression
!
! SUBROUTINE ng_regline_stats(N, X, Y, b,&
!                             Yavg   , Yvar   , Ystd   , Xavg   , Xvar   , Xstd   ,&
!                             bstd   , Yest   , Yres   , SST    , SSR    , SSE    ,&
!                             MST    , MSR    , MSE    , MSE_dof, RSE    , RSE_dof,&
!                             F      , r2     , r      , fuv    , r2a    , F_dof  ,&
!                             F_pval , stderr , tval   , pval   , b95    , y95    ,&
!                             YMR025 , YMR975 , YPI025 , YPI975 , print_anova)
!
! SUBROUTINE ng_reg_multlin(n, m, y, ymsg, x, xmsg, c, sc) ! multiple linear regression
!
! SUBROUTINE ng_reg_multlin_stats(N, NP, Y, XP, b,&        ! multiple linear regression + confidence estimates
!                                 Yavg   , Yvar   , Ystd   , Xavg   , Xvar   , Xstd   ,&
!                                 bstd   , Yest   , Yres   , SST    , SSR    , SSE    ,&
!                                 MST    , MSR    , MSE    , MSE_dof, RSE    , RSE_dof,&
!                                 F      , r2     , r      , fuv    , r2a    , F_dof  ,&
!                                 F_pval , stderr , tval   , pval   , print_anova)
!
! SUBROUTINE ng_trend_manken(x, n, prob, trend) ! Mann-Kendall non-parametric test for monotonic trend
!
! SUBROUTINE ng_cdft_t   ( p, df, t ) ! calculate t-value given the probability and degrees of freedom
! SUBROUTINE ng_cdft_p   ( t, df, p ) ! calculate the probability given t-value and degrees of freedom
! SUBROUTINE ng_student_t( t, df, p ) ! Calculates the two-tailed probability of the Student-t distribution.
!
! SUBROUTINE ng_ttest( AVE1, VAR1, N1, AVE2, VAR2, N2, IFLAG, ALPHA, TVAL, IER )
! SUBROUTINE ng_ftest( VAR1, N1, VAR2, N2, ALPHA, IER )
! SUBROUTINE ng_rtest( R, N, PROB )
! SUBROUTINE ng_equiv_sample_size( X, NPTS, XMSG, SIGLVL, NEQV )
!
! SUBROUTINE ng_esacr( x, npts, xmsg, mxlag, acr, ier ) ! auto-correlations
! SUBROUTINE ng_esacv( x, npts, xmsg, mxlag, acv, ier ) ! auto-covariances
!
! SUBROUTINE ng_esccr ( x, y, npts, xmsg, ymsg, mxlag, ccr, ier ) ! cross-correlations
! SUBROUTINE ng_esccv ( x, y, npts, xmsg, ymsg, mxlag, ccv, ier ) ! cross-covariances
!
! SUBROUTINE ng_escorc( x, y, npts, xmsg, ymsg,        ccr, ier ) ! cross-correlation at lag 0 only
! SUBROUTINE ng_escovc( x, y, npts, xmsg, ymsg,        ccv, ier ) ! cross-covariance at lag 0 only
!
! SUBROUTINE ng_lspoly( M, X, Y, WGT, N, COEF ) ! weighted least squares polynomial fit
!
! SUBROUTINE ng_dtrend( x, npts, slope, yint )  ! remove the least squares linear trend
! SUBROUTINE ng_dtrend_quadratic( x, npts, coeff )
! SUBROUTINE ng_dtrend_msg( x, y, npts, xmsg, ymsg, iopt, ydt, slope, yint )
!
! SUBROUTINE ng_taper(n, x, p, iopt) ! apply split-cosine-bell tapering
!
! SUBROUTINE ng_specx_anal( x, nx, iopt, jave, pct, scl, spcx, frq,&      ! spectra of series
!                           df, bw, xavei, xvari, xvaro, xlag1, xslope)
! SUBROUTINE ng_specxy_anal( x, y, n, iopt, jave, pct, scl,&
!                            frq, spcx, spcy, cospc, quspc, coher, phase,&
!                            df, bw, coherp,&
!                            xavei, xvari, xvaro, xlag1, xslope,&
!                            yavei, yvari, yvaro, ylag1, yslope)
!
! SUBROUTINE ng_specx_ci( nspc, spcx, frq, xlag1, df, plow, phign, splt ) ! spectrum and confidence curves
! SUBROUTINE ng_specxy_ci( nspc, spcx, spcy, frq, xlag1, ylag1, df, plow, phigh, splt )
!
! REAL FUNCTION ng_chiinv( p, df ) ! inverse chi-squared distribution
!
! SUBROUTINE ng_wavelet(n, y, mother, dt, param, s0, dj, jtot, npad,&
!                       noise, isigtest, siglvl, nadof, wave,&
!                       power, phase, mean, stdev, lag1, r1, dof, scale,&
!                       period, gws, coi, fft_theor, signif, cdelta, psi0) ! the wavelet transform
!
! SUBROUTINE ng_pdfx( nx, x, xmsg, nbins, bin_bounds, pdf )
! SUBROUTINE ng_pdfxy( nxy, x, y, xmsg, ymsg, nbinx, nbiny, binx_bounds, biny_bounds, pdf )
! SUBROUTINE ng_pdfxy_conform( nx, x, xmsg, ny, y, ymsg, nbinx, nbiny, binx_bounds, biny_bounds, pdf )
!
! SUBROUTINE ng_center_finite_diff(npts, q, r, qmsg, rcyc, dqdr)
!
!---------------------------------------------------------------------
!
! SUBROUTINE NG_PQSORT(X, N, KFLAG, IPERM) ! Quick sorting
!
!   INTEGER, INTENT(IN   ) :: N
!   REAL,    INTENT(IN   ) :: X(N)
!   INTEGER, INTENT(IN   ) :: KFLAG
!   INTEGER, INTENT(  OUT) :: IPERM(N)
!
! Routine to return the permutation vector IPERM generated by sorting
! the array X. Array X may be sorted in increasing or decreasing order.
!
! Variables:
!
!   X     - real array of values to be sorted.
!
!   N     - number of values in array X to be sorted.
!
!   KFLAG - control parameter:
!
!           =+1, means return the permutation vector resulting from
!                sorting X in increasing order
!
!           =-1, means return the permutation vector resulting from
!                sorting X in decreasing order
!
!   IPERM - permutation array such that IPERM(I) is the index of
!           the value in the original order of the X array that is
!           in the Ith location in the sorted order.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_sum(x, npts, xmsg, xsum, nptused)
!
! Routine to compute the sum of a variable
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts), xmsg
!   REAL,    INTENT(  OUT) :: xsum
!   INTEGER, INTENT(  OUT), OPTIONAL :: nptused
!
! this routine will calculate estimates of the sum
! .   of the vector x containing missing data.
!
! input arguments:
! .   x        - input vector
! .   npts     - length of x
! .   xmsg     - missing code: if there are no msg values
! .                            set xmsg to some value which will
! .                            not be encountered.
!
! output arguments:
! .   sum      - sum of x
! .   nptused  - no. of points used in computing various quantities
!
! note :
! .   sum will be set to xmsg for the case of all values of x are xmsg
! .   nptused will be set to 0 for the case of all values of x are xmsg
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_avg( x, npts, xmsg, avg, nptused )
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts), xmsg
!   REAL,    INTENT(  OUT) :: avg
!   INTEGER, INTENT(  OUT), OPTIONAL :: nptused
!
! this routine will calculate estimates of the average
! .   of the vector x containing missing data.
!
! input arguments:
! .   x        - input vector
! .   npts     - length of x
! .   xmsg     - missing code: if there are no msg values
! .                            set xmsg to some value which will
! .                            not be encountered.
!
! output arguments:
! .   avg      - average of x
! .   nptused  - no. of points used in computing various quantities
!
! note :
! .   avg will be set to xmsg for the case of all values of x are xmsg
! .   nptused will be set to 0 for the case of all values of x are xmsg
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_stddev( x, npts, xmsg, std, nptused )
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts), xmsg
!   REAL,    INTENT(  OUT) :: std
!   INTEGER, INTENT(  OUT), OPTIONAL :: nptused
!
! this routine will calculate estimates of the standard deviation
! .   of the vector x containing missing data.
!
! input arguments:
! .   x        - input vector
! .   npts     - length of x
! .   xmsg     - missing code: if there are no msg values
! .                            set xmsg to some value which will
! .                            not be encountered.
!
! output arguments:
! .   std      - atandard deviation of x
! .   nptused  - no. of points used in computing various quantities
!
! note :
! .   std will be set to xmsg for the case of all values of x are xmsg
! .   nptused will be set to 0 for the case of all values of x are xmsg
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_median(x, npts, xmsg, xmedian, xmrange, xrange, nptused)
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts), xmsg
!   REAL,    INTENT(  OUT) :: xmedian
!   REAL,    INTENT(  OUT), OPTIONAL :: xmrange, xrange
!   INTEGER, INTENT(  OUT), OPTIONAL :: nptused
!
! Routine to find the median, range and mid-range of the input
! vector x containing missing data.
!
! Variables:
!
! npts     - length of x
!
! x        - input vector (series)
!
! xmsg     - missing code: if no msg values set to some number
!                          which will not be encountered.
!
! xmedian  - median value of vector x
!
! nptused  - no. of points used in computing various quantities
!
! xmrange  - midrange, 0.5*(xmax+xmin)
!
! xrange   - range of x, xmax-xmin
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_stat1(x, npts, xmsg, xmean, nptused)
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts)
!   REAL,    INTENT(IN   ) :: xmsg
!   REAL,    INTENT(  OUT) :: xmean
!   INTEGER, INTENT(  OUT), OPTIONAL :: nptused
!
! Routine to calculate estimates of the first moment of the
! vector x containing missing data.
!
! Variables:
!
! npts    - length of x
!
! x       - input vector
!
! xmsg    - missing code: if there are no msg values
!                         set xmsg to some value which will
!                         not be encountered.
!
! xmean   - mean of x (first moment)
!
! nptused - no. of points used to calculate the estimates
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_stat2(x, npts, xmsg, xmean, xvar, nptused)
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts)
!   REAL,    INTENT(IN   ) :: xmsg
!   REAL,    INTENT(  OUT) :: xmean, xvar
!   INTEGER, INTENT(  OUT), OPTIONAL :: nptused
!
! Routine to calculate estimates of the first two moments of the
! vector x containing missing data.
!
! Variables:
!
! npts    - length of x
!
! x       - input vector
!
! xmsg    - missing code: if there are no msg values
!                         set xmsg to some value which will
!                         not be encountered.
!
! xmean   - mean of x (first moment)
!
! xvar    - sample variance of x (second moment)
!
! nptused - no. of points used to calculate the estimates
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_stat2_trim(x, npts, xmsg, ptrim, xmean, xvar, nptused)
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts)
!   REAL,    INTENT(IN   ) :: xmsg
!   REAL,    INTENT(IN   ) :: ptrim
!   REAL,    INTENT(  OUT) :: xmean, xvar
!   INTEGER, INTENT(  OUT), OPTIONAL :: nptused
!
! Routine to calculate trimmed estimates of the first two moments
! of the vector x containing missing data.
!
! Variables:
!
! npts    - length of x
!
! x       - input vector
!
! xmsg    - missing code: if there are no msg values
!                         set xmsg to some value which will
!                         not be encountered.
!
! ptrim   - portion of the series to be trimmed (0.0<= ptrim <1.0)
!           if (ptrim ==  0.0) then
!               calculate whole series mean and variance
!           else
!               a minimum of two pts will be trimmed
!               a maximum of n-2 pts will be trimmed
!           end if
!
!           note: if you want to be very conservative and only
!                 trim the min and max values then set
!                 ptrim to some very small value (e.g. 1.e-36)
!
!           ex: n=45, ptrim=0.5 then
!               0.5*45=22 pts will be trimmed (11 on each end)
!
! xmean   - mean of x (first moment)
!
! xvar    - sample variance of x (second moment)
!
! nptused - no. of points used to calculate the estimates
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_stat4(x, npts, xmsg, xmean, xvar, xskew, xkurt, nptused)
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts)
!   REAL,    INTENT(IN   ) :: xmsg
!   REAL,    INTENT(  OUT) :: xmean, xvar, xskew, xkurt
!   INTEGER, INTENT(  OUT), OPTIONAL :: nptused
!
! Routine to calculate estimates of the first four moments of the
! vector x containing missing data.
!
! Variables:
!
! npts    - length of x
!
! x       - input vector
!
! xmsg    - missing code: if there are no msg values
!                         set xmsg to some value which will
!                         not be encountered.
!
! xmean   - mean of x (first moment)
!
! xvar    - sample variance of x (second moment)
!
! xskew   - coef. of skewness (third moment)
!           departure from symmetry. if skew>0 [skew<0] the
!           distribution trails off to the right [left] .
!
! xkurt   - coef. of kurtosis (fourth moment)
!           the normal distribution has a kurtosis of 3 . this
!           value is subtracted from the calculated kurtosis.
!           thus neg values are possible and the returned value
!           is kurtosis relative to the normal distribution.
!           if (kurt-3) > 0 [<0] it is usually more sharply peaked
!           [flatter] than the normal distribution. (leptokurtic and
!           platykurtic , respectively.) e.g. , a rectangular function has
!           a kurtosis of 1.8 or 1.8-3 = -1.2 relative to the normal
!           distribution.
!
! nptused - no. of points used to calculate the estimates
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_stat_dispersion(x, npts, xmsg, statx, PrintStat)
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts)
!   REAL,    INTENT(IN   ) :: xmsg
!   REAL,    INTENT(  OUT) :: statx(30)
!   LOGICAL, INTENT(IN   ), OPTIONAL :: PrintStat
!
! Routine to compute a number of robust dispersion statistics.
!
! Variables:
!
!   x     - data array
!
!   npts  - size of array x
!
!   xmsg  - missing value of x
!
!   statx - the calculated statistics array, 30 elements
!
!   PrintStat - print the calculated statistics, if present with .TRUE.
!
! This routine is intended for large dataset sizes. It sorts the
! non-missing data values and uses the index values to extract the
! dectile, octile, sextile, quartile, tritile values.
!
! Currently the returned statistics (here, STATX) include:
!
!   statx( 1) - average of all values
!   statx( 2) - standard deviation
!   statx( 3) - minimum
!   statx( 4) - lower dectile
!   statx( 5) - lower octile
!   statx( 6) - lower sextile
!   statx( 7) - lower quartile
!   statx( 8) - lower tritile
!   statx( 9) - median
!   statx(10) - upper tritile
!   statx(11) - upper quartile
!   statx(12) - upper sextile
!   statx(13) - upper octile
!   statx(14) - upper dectile
!   statx(15) - maximum
!   statx(16) - Max(x) - Min(x)
!   statx(17) - Range/STATX(1)
!   statx(18) - sqrt( (x-xAvg)^2/N ) where N=# non-missing values
!   statx(19) - Total number of input values
!   statx(20) - Number of input values used for statistics
!   statx(21) - Number of missing values
!   statx(22) - percent of missing values
!   statx(23) - lower 0.1%   => 0.1th percentile
!   statx(24) - lower 1.0%   => 1th
!   statx(25) - lower 5.0%   => 5th
!   statx(26) - upper 5.0%   => 95th percentile
!   statx(27) - upper 1.0%   => 99th
!   statx(28) - Upper 0.1%   => 99.9th
!   statx(29) - Skewness
!   statx(30) - Kurtosis
!
! Note: statx(23 to 28) require more than 1000 observations
!       Otherwise, they are set to missing value
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_sum_wgt( x, npts, xmsg, wgt, iopt, xsum )
!
! Routine to compute the weighted sum of a variable
!
!   INTEGER, INTENT(IN   ) :: npts, iopt
!   REAL,    INTENT(IN   ) :: x(npts), wgt(npts), xmsg
!   REAL,    INTENT(  OUT) :: xsum
!
! Note:
!
!   (a) opt=0 means compute the weighted sum only if all values
!       are not missing;
!
!   (b) opt=1 means compute the weighted sum of all non-missing values;
!
!   (c) opt>1 means to return the sum only if the number of non-missing
!       values is greater-then or equal to opt.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_avg_wgt( x, npts, xmsg, wgt, iopt, xavg )
!
! Routine to compute the weighted average of a variable
!
!   INTEGER, INTENT(IN   ) :: npts, iopt
!   REAL,    INTENT(IN   ) :: x(npts), wgt(npts), xmsg
!   REAL,    INTENT(  OUT) :: xavg
!
! Note:
!
!   (a) opt=0 means compute the weighted average only if all values
!       are not missing;
!
!   (b) opt=1 means compute the weighted mean of all non-missing values;
!
!   (c) opt>1 means to return the mean only if the number of non-missing
!       values is greater-then or equal to opt.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_rmsd( x, y, npts, xmsg, ymsg, xyrmsd )
!
! Routine to calculate the root-mean-square-difference between two
! variables
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts), y(npts)
!   REAL,    INTENT(IN   ) :: xmsg, ymsg
!   REAL,    INTENT(  OUT) :: xyrmsd
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_rmvmean( x, npts, xmsg )
!
! Routine to remove the series mean from a series
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(INOUT) :: x(npts)
!   REAL,    INTENT(IN   ) :: xmsg ! missing value
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_rmvmed( x, npts, xmsg )
!
! Routine to remove the series median from a series
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(INOUT) :: x(npts)
!   REAL,    INTENT(IN   ) :: xmsg ! missing value
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_standardize( x, npts, xmsg, iopt )
!
! Routine to remove the mean from a series and standardize by the
! standard deviation (sample or pop)
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(INOUT) :: x(npts)
!   REAL,    INTENT(IN   ) :: xmsg ! missin g value
!   INTEGER, INTENT(IN   ) :: iopt ! population or sample
!
! Note: Setting iopt=1 means to use the population standard deviation
!       (i.e., divide by the number of non-missing value [npts]).
!       Otherwise, the sample standard deviation is used for
!       normalization (i.e., divide by [npts-1]).
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_runave( x, npts, nave, kopt, xmsg )
!
!   INTEGER, INTENT(IN   ) :: NPTS
!   REAL,    INTENT(INOUT) :: X(NPTS)
!   INTEGER, INTENT(IN   ) :: NAVE, KOPT
!   REAL,    INTENT(IN   ) :: XMSG
!
! this routine will perform a running average on x
! .   the end points may be treated in three different ways
!
! nomenclature:
! .   x         - on input the series to be smoothed
! .               on output the smoothed series
!
! .   npts      - no of pts in x
!
! .   nave      - no. of pts to be utilized in the running average
!
! .   kopt      - end-point option [prefer an odd number]
! .               kopt < 0 : utilize cyclic conditions
! .                          e.g.,  nave=3 at n=1 and n=npts
! .                          x(1)    = (x(npts)+x(1)+x(2)) / 3.
! .                          x(npts) = (x(npts-1)+x(npts)+x(1)) / 3.
! .                          e.g.,  nave=4 at n=1 and n=npts
! .                          x(1)    = (x(npts)+x(1)+x(2)+x(3)) / 4.
! .                          x(npts) = (x(npts-2)+x(npts-1)+x(npts)+x(1)) / 4.
! .               kopt = 0 : set unsmoothed beginning and end pts to xmsg
! .                          e.g.,  nave=3 , x(1) = xmsg and x(npts) = xmsg
! .                          e.g.,  nave=4 , x(1) = xmsg and x(2) = xmsg and x(npts) = xmsg
! .               kopt > 0 : utilize reflective (symmetric) conditions
! .                          e.g.,  nave=3 at n=1 and n=npts
! .                          x(1)    = (x(2)+x(1)+x(2)) / 3.
! .                          x(npts) = (x(npts-1)+x(npts)+x(npts-1)) /3.
! .                          e.g.,  nave=4 at n=1 and n=npts
! .                          x(1)    = (x(3)+x(2)+x(1)+x(2)) / 4.
! .                          x(npts) = (x(npts-2)+x(npts-1)+x(npts)+x(npts-1)) /4.
!
! .   xmsg      - missing/special value
! .               also; if kopt=0 set end points to this special value
!
!--------------------------------------------------------------------
!
! SUBROUTINE ng_wgt_runave( x, npts, wgt, nwgt, kopt, xmsg )
!
!   INTEGER, INTENT(IN   ) :: NPTS
!   REAL,    INTENT(INOUT) :: X(NPTS)
!   INTEGER, INTENT(IN   ) :: NWGT
!   REAL,    INTENT(IN   ) :: WGT(NWGT)
!   INTEGER, INTENT(IN   ) :: KOPT
!   REAL,    INTENT(IN   ) :: XMSG
!
! this routine will perform a weighted running average on x
! .   the end points may be treated in three different ways
!
! nomenclature:
! .   x         - on input the series to be smoothed
! .               on output the smoothed series
!
! .   npts      - no of pts in x
!
! .   wgt       - vector containing weights [length=nwgt]
!
! .   nwgt      - no. of pts to be utilized in the wgted running average
!
! .   kopt      - end-point option [prefer an odd number]
! .               kopt < 0 : utilize cyclic conditions
! .                          e.g.,  nwgt=3 at n=1 and n=npts and wsum=SUM{wgt}
! .                          x(1)    = w(1)*x(npts)+w(2)*x(1)+w(3)*x(2)
! .                          x(npts) = w(1)*x(npts-1)+w(2)*x(npts)+w(3)*x(1)
! .                          e.g.,  nwgt=4 at n=1 and n=npts
! .                          x(1)    = w(1)*x(npts-1)+w(2)*x(npts)+w(3)*x(1)+w(4)*x(2)
! .                          x(npts) = w(1)*x(npts-2)+w(2)*x(npts-1)+w(3)*x(npts)+w(4)*x(1)
! .               kopt = 0 : set unsmoothed beginning and end pts to xmsg
! .                          e.g.,  nwgt=3 , x(1) = xmsg and x(npts) = xmsg
! .                                        , x(2) = w(1)*x(1)+w(2)*x(2)+w(3)*x(3)
! .                          e.g.,  nwgt=4 , x(1) = xmsg and x(2) = xmsg
! .                                        , x(3) = w(1)*x(1)+w(2)*x(2)+w(3)*x(3)+w(4)*x(4)
! .                                     x(npts-1) = xmsg, x(npts) = xmsg
! .               kopt > 0 : utilize reflective (symmetric) conditions
! .                          e.g.,  nwgt=3 at n=1 and n=npts
! .                          x(1)    = w(1)*x(2)+w(2)*x(1)+w(3)*x(2)
! .                          x(npts) = w(1)*x(npts-1)+w(2)*x(npts)+w(3)*x(npts-1)
! .                          e.g.,  nwgt=4 at n=1 and n=npts
! .                          x(1)    = w(1)*x(3)+w(2)*x(2)+w(3)*x(1)+w(4)*x(2)
! .                          x(npts) = w(1)*x(npts-2)+w(2)*x(npts-1)+w(3)*x(npts)+w(4)*x(npts-1)
!
! .   xmsg      - missing/special value
! .               also; if kopt=0 set end points to this special value
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_filwgt_normal( wt, nwt, sigma, itype )
!   INTEGER, INTENT(IN   ) :: nwt
!   REAL,    INTENT(  OUT) :: wt(nwt)
!   REAL,    INTENT(IN   ) :: sigma
!   INTEGER, INTENT(IN   ) :: itype
!
! Routine to calculate one-dimensional filter weights based upon
! the normal (gaussian) distribution.
!
! wt:    Computed user specified number of weights, this routine
!        returns a symmetric set of weights.
!
! nwt:   A scalar indicating the total number of weights
!        (can be odd or even).
!
! sigma: A scalar indicating the standard deviation to be used.
!        Generally, this is set to 1.0.
!
! itype: A scalar that is currently not used.
!
! Note:
!
! Setting sigma < 1.0 will result in even more weight being given
! to the central values than sigma = 1.0.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_filwgts_lanczos( wt, nwt, ihp, fca, fcb, sigma, freq, resp )
!   INTEGER, INTENT(IN   ) :: nwt
!   REAL,    INTENT(  OUT) :: wt(nwt)
!   INTEGER, INTENT(IN   ) :: ihp
!   REAL,    INTENT(IN   ) :: fca, fcb, sigma
!   REAL,    INTENT(  OUT), OPTIONAL :: freq(2*nwt-1), resp(2*nwt-1)
!
! Routine to calculate filter wgts and the associated response function
!
! Input parameters :
!
!     nwt     total number of weights (an odd number; nwt.ge.3)
!             the more wgts .... the better the filter but there
!             is a greater loss of data.
!
!     ihp     if low-pass filter ihp = 0,
!             if high-pass ihp = 1,
!             if band-pass ihp = 2.
!
!     fca     the cut-off freq of the ideal high or
!             low-pass filter: [ 0.0 < fca < 0.5 ]
!
!     fcb     used only when a band-pass filter is desired,
!             in which case it is the cut-off freq for the
!             second low-pass filter:  [ fca < fcb < 0.5 ]
!
!     sigma   the power of the sigma factor.  it is
!             greater than or equal to zero.
!             note: sigma=1 to 3 is usually good enough.
!
! Output parameters :
!
!     wt      vector containing the computed wgts. its length is nwt.
!             the central weight is located at nwt/2+1.
!
!     resp    the array of responses at freq intvls
!             of 0.5/(2*nwt-2)  cycles/data intvl from the
!             origin to the nyquist.  its length is 2*nwt-1.
!
!     freq    the array of freqs at intvls of 0.5/(2*nwt-2)
!             cycles/data intvl at which the responses
!             are calculated.  its length is 2*nwt-1 .
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_bw_bandpass_filter( x, y, n, fca, fcb, m, dt, mzer, e )
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n)
!   REAL,    INTENT(  OUT) :: y(n)
!   INTEGER, INTENT(IN   ) :: m, mzer
!   REAL,    INTENT(IN   ) :: fca, fcb, dt
!   REAL,    INTENT(  OUT), OPTIONAL :: e(n)
!
! Routine to apply a Butterworth bandpass filter optimized for
! narrow bandwidths to time series.
!
! INPUT:
!
! n:      Number of input, output time series points
! x(n):   Input (real) time series
! fca:    A scalar indicating the cut-off frequency of the ideal
!           band pass filter: (0.0 < fca < 0.5).
! fcb:    A scalar indicating the cut-off frequency of the ideal
!           band pass filter: (0.0 < fcb < 0.5) and (fcb > fca).
!
! m:      Order of filter; 4 <= m <= 6 should be adequate for most
!         applications. Currently, the maximum value allowed is 10.
! dt:     Time series sampling interval
! mzer:   Integer flag to remove mean (0 no, 1 yes)
!
!         In general, m=6, dt=1.0, and, mzer=1 are suggested
!
! OUTPUT:
!
! y(n):   Output filtered (real) time series
! e(n):   Output envelope function for filtered time series
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_demod_cmplx(ntim, x, frqdem, frqcut, nwt, opt, xamp, xpha)
!
!   INTEGER, INTENT(IN   ) :: ntim
!   REAL,    INTENT(IN   ) :: x(ntim)
!   REAL,    INTENT(IN   ) :: frqdem, frqcut
!   INTEGER, INTENT(IN   ) :: nwt
!   LOGICAL, INTENT(IN   ) :: opt
!   REAL,    INTENT(  OUT) :: xamp(ntim), xpha(ntim)
!
! Routine to perform a complex demodulation on a time series.
! Complex demodulation is a technique for analyzing nonstationary time
! series by estimating the instantaneous amplitude and phase of a given
! harmonic component.
!
! Variables:
!
! ntim   - Length of the time series
!
! x      - The given time series
!
! frqdem - The demodulation frequency (cycles per data point).
!          The choice of frqdem may be guided by theory or by a (say)
!          Fourier analysis (e.g., a periodogram) of a series.
!          The range: 0.0 < frqdem < 0.5
!
! frqcut - The cutoff frequency.  Typically, frqcut=frqdem or
!          frqcut=0.50*frqdem or frqcut=0.75*frqdem. Note: nwt should
!          be set such that it passes the desired information.
!
! nwt    - The total number of weights (must be an odd number; nwt >= 3).
!          The more weights, the better the filter, but there is a greater
!          loss of data.
!
! xamp   - The estimated amplitudes
!
! xpha   - The estimated phases
!
! Note: This technique fails when the frequency of oscillation differs
! from the modulation frequency by more than the cutoff frequency of
! the low-pass filter.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_ezfftf( npts, x, xbar, cf )
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts)
!   REAL,    INTENT(  OUT) :: xbar
!   REAL,    INTENT(  OUT) :: cf(npts/2,2)
!
! Routine to perform a Fourier analysis on a real periodic sequence.
!
! npts:   The length of the array x to be transformed.
!
! x:      A real array of length npts which contains the sequence
!         to be transformed. r is not destroyed.
!
! xbar:   The series mean of the array x
!
! cf:     The fourier coefficients dimensioned (npts/2,2) contains
!         the real and imaginary coefficients.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_ezfftb( npts, xbar, cf, x )
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: xbar
!   REAL,    INTENT(IN   ) :: cf(npts/2,2)
!   REAL,    INTENT(  OUT) :: x(npts)
!
! Routine to perform a Fourier synthesis from real and imaginary
! coefficients to compute a real perodic sequence.
!
! npts:   The length of the array x to be transformed.
!
! xbar:   The constant Fourier coefficient. (series mean of array x)
!
! cf:     The Fourier coefficients as created by ezfftf. The elements
!         cf(:,1) are the real coefficients, and cf(:,2) are the
!         imaginary coefficients.
!
! x:      The computed series using the coefficients cf and the value
!         of xbar.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_fourier_info( nx, x, nhx, sclPha, finfo )
!
!   INTEGER, INTENT(IN   ) :: nx
!   REAL,    INTENT(IN   ) :: x(nx)
!   INTEGER, INTENT(IN   ) :: nhx
!   REAL,    INTENT(IN   ) :: sclPha
!   REAL,    INTENT(  OUT) :: finfo(nhx,3)
!
! Routine to prform Fourier analysis on a periodic series.
!
! Variables:
!
!   nx     - Size of array x
!
!   x      - A one dimensional periodic array, the harmonic analysis
!            will be performed. The periodic (i.e. cyclic) point
!            should not be included. Missing values are not allowed.
!
!   sclPha - Constant which will be used to scale the phases. If no
!            scaling is desired, set sclPhase=1.0.
!
!   nhx    - The number of harmonics to be returned. 1 <= nhx <= n/2.
!
!   finfo  - Returned two dimensional array. The second dimension size
!            is three (3), where the subscripts 1, 2, and 3 reference
!
!            finfo(:,1) the amplitude of each harmonic
!            finfo(:,2) the phase of each harmonic
!            finfo(:,3) the percent variance explained by each harmonic
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_regline( x, y, npts, xmsg, ymsg, rcoef, yint,&
!                        rstd, tval, xave, yave, nptxy )
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts), y(npts), xmsg, ymsg
!   REAL,    INTENT(  OUT) :: rcoef, yint
!   REAL,    INTENT(  OUT), OPTIONAL :: rstd, tval, xave, yave
!   INTEGER, INTENT(  OUT), OPTIONAL :: nptxy
!
! this routine will calculate the regression coef (trend, slope,..),
! .   x and y averages, the t-statistic and the number of pts used
! .   missing data are allowed.
!
! input arguments :
! .   x,y      - input vectors
! .   npts     - length of vectors x and y
! .   xmsg,ymsg- missing code: if no msg values set to some number
! .              which will not be encountered.
!
! output arguments :
! .   rcoef    - slope (trend ... regression coef)
! .   yint     - y-intercept
!
! .   rstd     - standard deviation of the regression coefficient
! .   tval     - t-statistic (null hypothesis: H0: r=0.0)
! .   xave     - average of x
! .   yave     - average of y
! .   nptxy    - number of points used
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_regline_stats(N, X, Y, b,&
!                             Yavg   , Yvar   , Ystd   , Xavg   , Xvar   , Xstd   ,&
!                             bstd   , Yest   , Yres   , SST    , SSR    , SSE    ,&
!                             MST    , MSR    , MSE    , MSE_dof, RSE    , RSE_dof,&
!                             F      , r2     , r      , fuv    , r2a    , F_dof  ,&
!                             F_pval , stderr , tval   , pval   , b95    , y95    ,&
!                             YMR025 , YMR975 , YPI025 , YPI975 , print_anova)
!
! Routine to perform simple linear regression including confidence estimates
!
!             Y(i) ~ b(0) + b(1)*X(i)
!
! where the b(0) is the y-intercept and b(1) is the slope (regression coefficients)
!
! Note: missing values for X and Y arrays are NOT allowed.
!
!-------------------
!
! Variables:
!
!   INTEGER, INTENT(IN   ) :: N                     ! dimensions of arrays X and Y
!   REAL,    INTENT(IN   ) :: X(N), Y(N)            ! independent variables X(N), dependent variables Y(N)
!   REAL,    INTENT(  OUT) :: b(0:1)                ! y-intercept b(0), and, slope (linear regression coefficient) b(1)
!
!---------
!
!   REAL,    INTENT(  OUT), OPTIONAL :: Yavg        ! Y-average
!   REAL,    INTENT(  OUT), OPTIONAL :: Yvar        ! Y-variance
!   REAL,    INTENT(  OUT), OPTIONAL :: Ystd        ! Y-standard deviation
!
!   REAL,    INTENT(  OUT), OPTIONAL :: Xavg        ! X-average
!   REAL,    INTENT(  OUT), OPTIONAL :: Xvar        ! X-variance
!   REAL,    INTENT(  OUT), OPTIONAL :: Xstd        ! X-standard deviation
!
!   REAL,    INTENT(  OUT), OPTIONAL :: bstd        ! standardized linear regression coefficients
!
!   REAL,    INTENT(  OUT), OPTIONAL :: Yest(N)     ! model estimates,                 Yest = b(0) + b(1)* + b(2)* + ...
!   REAL,    INTENT(  OUT), OPTIONAL :: Yres(N)     ! residuals,                       Yres = Yest-Y
!
!   REAL,    INTENT(  OUT), OPTIONAL :: SST         ! Total sum of squares,            SST = sum((Y-Yavg)^2)
!   REAL,    INTENT(  OUT), OPTIONAL :: SSR         ! Model/Regression Sum of Squares, SSR = sum((Yest-Yavg)^2)
!   REAL,    INTENT(  OUT), OPTIONAL :: SSE         ! Error/Residual Sum of Squares,   SSE = sum(Yres^2)
!
!   REAL,    INTENT(  OUT), OPTIONAL :: MST         ! Total Mean Square,               MST = SST/REAL(N-1)
!   REAL,    INTENT(  OUT), OPTIONAL :: MSR         ! Model/Regression Mean Square,    MSR = SSR/REAL(NP )
!   REAL,    INTENT(  OUT), OPTIONAL :: MSE         ! Error/Residual Mean Square,      MSE = SSE/REAL(N-NP-1)
!   INTEGER, INTENT(  OUT), OPTIONAL :: MSE_dof     ! degree of freedom,               MSE_dof = N-NP-1
!
!   REAL,    INTENT(  OUT), OPTIONAL :: RSE         ! residual standard error,         RSE = SQRT(MSE)
!   INTEGER, INTENT(  OUT), OPTIONAL :: RSE_dof     ! degree of freedom,               RSE_dof = N-M-1
!
!   REAL,    INTENT(  OUT), OPTIONAL :: F           ! F-statistic, F = MSR/MSE
!
!   REAL,    INTENT(  OUT), OPTIONAL :: r2          ! square of the Pearson correlation coefficient, r2  = SSR/SST
!   REAL,    INTENT(  OUT), OPTIONAL :: r           ! multiple (overall) correlation,                r   = SQRT(r2)
!   REAL,    INTENT(  OUT), OPTIONAL :: fuv         ! fraction of variance *unexplained*,            fuv = 1.0 - r2
!   REAL,    INTENT(  OUT), OPTIONAL :: r2a         ! adjusted r2... better for small N,             r2a = r2-fuv*REAL(NP)/REAL(N-NP-1)
!
!   INTEGER, INTENT(  OUT), OPTIONAL :: F_dof(2)    ! degree of freedom, F_dof = (/NP,N-NP-1/)
!   REAL,    INTENT(  OUT), OPTIONAL :: F_pval      ! student t-statistic
!
!   REAL,    INTENT(  OUT), OPTIONAL :: stderr(2)   ! standard error of coefficients
!   REAL,    INTENT(  OUT), OPTIONAL :: tval  (2)   ! t-values
!   REAL,    INTENT(  OUT), OPTIONAL :: pval  (2)   ! p-values
!
!   REAL,    INTENT(  OUT), OPTIONAL :: b95(2)      !  2.5% and 97.5% slope       confidence intervals
!   REAL,    INTENT(  OUT), OPTIONAL :: y95(2)      !  2.5% and 97.5% y-intercept confidence intervals
!
!   REAL,    INTENT(  OUT), OPTIONAL :: YMR025(N)   !  2.5% mean response
!   REAL,    INTENT(  OUT), OPTIONAL :: YMR975(N)   ! 97.5% mean response
!
!   REAL,    INTENT(  OUT), OPTIONAL :: YPI025(N)   !  2.5% predition interval
!   REAL,    INTENT(  OUT), OPTIONAL :: YPI975(N)   ! 97.5% predition interval
!
!   LOGICAL, INTENT(IN   ), OPTIONAL :: print_anova ! .TRUE. will print the ANOVA table (default is .FALSE.)

!---------------------------------------------------------------------
!
! SUBROUTINE ng_reg_multlin(n, m, y, ymsg, x, xmsg, c, sc)
!
!   INTEGER, INTENT(IN   ) :: n, m
!   REAL,    INTENT(IN   ) :: y(n), ymsg, x(n,m), xmsg
!   REAL,    INTENT(  OUT) :: c(0:m)
!   REAL,    INTENT(  OUT), OPTIONAL :: sc(m)
!
! Routine to prform basic multiple linear regression analysis.
!
! The modelled regession time series y(i) (i=1,2,...,n) is given by
!
!                            m
!             y(i) ~ c(0) + SUM c(j)*x(i,j)
!                           j=1
!
! where c(j) = regression coefficient for j-th input surrogate time
! series x(i,j), c(0) is the y-intercept
!
! Variables:
!
! n - Time series length
!
! m - Number of surrogate series x
!
! y - Time series, a one-dimensional array of length n containing
!     the dependent variable [y(n)].
!
! x - Surrogate series, a two-dimensional array of size [x(n,m)]
!     where m is the number of independent variables.
!
! ymsg - Missing value of variable y
!
! xmsg - Missing value of variable x
!
! c - y-intercept and partial regression coefficients
!     c(0) is the y-intercept, and,
!     c(1:m) are the partial correlation coefficients
!
! sc - Standardized partial correlation coefficients
!
!      sc(j) = c(j)*standard_deviation(x(:,j))/standard_deviation(y)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_reg_multlin_stats(N, NP, Y, XP, b,&
!                                 Yavg   , Yvar   , Ystd   , Xavg   , Xvar   , Xstd   ,&
!                                 bstd   , Yest   , Yres   , SST    , SSR    , SSE    ,&
!                                 MST    , MSR    , MSE    , MSE_dof, RSE    , RSE_dof,&
!                                 F      , r2     , r      , fuv    , r2a    , F_dof  ,&
!                                 F_pval , stderr , tval   , pval   , print_anova)
!
! Routine to perform multiple linear regression including confidence estimates.
!
! The modelled regession time series Y(i) (i=1,2,...,N) is given by
!
!                           NP
!             Y(i) ~ b(0) + SUM b(j)*XP(i,j)
!                           j=1
!
! where b(j) = regression coefficient for j-th input surrogate time
! series XP(i,j), b(0) is the Y-intercept
!
! Note: missing values for Y and XP arrays are NOT allowed.
!
!-------------------
!
! Variables:
!
!   INTEGER, INTENT(IN   ) :: N, NP                  ! dimensions of arrays Y and XP
!   REAL,    INTENT(IN   ) :: Y(N), XP(N,NP)         ! Y are the dependent variables, XP are the independent variables
!   REAL,    INTENT(  OUT) :: b(0:NP)                ! y-intercept b(0), and, partial regression coefficients b(1:NP)
!
!---------
!
!   REAL,    INTENT(  OUT), OPTIONAL :: Yavg         ! Y-average
!   REAL,    INTENT(  OUT), OPTIONAL :: Yvar         ! Y-variance
!   REAL,    INTENT(  OUT), OPTIONAL :: Ystd         ! Y-standard deviation
!
!   REAL,    INTENT(  OUT), OPTIONAL :: Xavg(NP)     ! X-average
!   REAL,    INTENT(  OUT), OPTIONAL :: Xvar(NP)     ! X-variance
!   REAL,    INTENT(  OUT), OPTIONAL :: Xstd(NP)     ! X-standard deviation
!
!   REAL,    INTENT(  OUT), OPTIONAL :: bstd(NP)     ! standardized partial regression coefficients
!
!   REAL,    INTENT(  OUT), OPTIONAL :: Yest(N)      ! model estimates,                 Yest = b(0) + b(1)* + b(2)* + ...
!   REAL,    INTENT(  OUT), OPTIONAL :: Yres(N)      ! residuals,                       Yres = Yest-Y
!
!   REAL,    INTENT(  OUT), OPTIONAL :: SST          ! Total sum of squares,            SST = sum((Y-Yavg)^2)
!   REAL,    INTENT(  OUT), OPTIONAL :: SSR          ! Model/Regression Sum of Squares, SSR = sum((Yest-Yavg)^2)
!   REAL,    INTENT(  OUT), OPTIONAL :: SSE          ! Error/Residual Sum of Squares,   SSE = sum(Yres^2)
!
!   REAL,    INTENT(  OUT), OPTIONAL :: MST          ! Total Mean Square,               MST = SST/REAL(N-1)
!   REAL,    INTENT(  OUT), OPTIONAL :: MSR          ! Model/Regression Mean Square,    MSR = SSR/REAL(NP )
!   REAL,    INTENT(  OUT), OPTIONAL :: MSE          ! Error/Residual Mean Square,      MSE = SSE/REAL(N-NP-1)
!   INTEGER, INTENT(  OUT), OPTIONAL :: MSE_dof      ! degree of freedom,               MSE_dof = N-NP-1
!
!   REAL,    INTENT(  OUT), OPTIONAL :: RSE          ! residual standard error,         RSE = SQRT(MSE)
!   INTEGER, INTENT(  OUT), OPTIONAL :: RSE_dof      ! degree of freedom,               RSE_dof = N-M-1
!
!   REAL,    INTENT(  OUT), OPTIONAL :: F            ! F-statistic, F = MSR/MSE
!
!   REAL,    INTENT(  OUT), OPTIONAL :: r2           ! square of the Pearson correlation coefficient, r2  = SSR/SST
!   REAL,    INTENT(  OUT), OPTIONAL :: r            ! multiple (overall) correlation,                r   = SQRT(r2)
!   REAL,    INTENT(  OUT), OPTIONAL :: fuv          ! fraction of variance *unexplained*,            fuv = 1.0 - r2
!   REAL,    INTENT(  OUT), OPTIONAL :: r2a          ! adjusted r2... better for small N,             r2a = r2-fuv*REAL(NP)/REAL(N-NP-1)
!
!   INTEGER, INTENT(  OUT), OPTIONAL :: F_dof(2)     ! degree of freedom, F_dof = (/NP,N-NP-1/)
!   REAL,    INTENT(  OUT), OPTIONAL :: F_pval       ! student t-statistic
!
!   REAL,    INTENT(  OUT), OPTIONAL :: stderr(NP+1) ! standard error of coefficients
!   REAL,    INTENT(  OUT), OPTIONAL :: tval  (NP+1) ! t-values
!   REAL,    INTENT(  OUT), OPTIONAL :: pval  (NP+1) ! p-values
!
!   LOGICAL, INTENT(IN   ), OPTIONAL :: print_anova  ! .TRUE. will print the ANOVA table (default is .FALSE.)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_trend_manken(x, n, prob, trend)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n)
!   REAL,    INTENT(  OUT) :: prob, trend
!
! Routine to calculate Mann-Kendall non-parametric test for monotonic
! trend and the Theil-Sen robust estimate of linear trend.
!
! x - time series to be tested.
!
! n - length of time series x
!
! prob - probability, the Mann-Kendall trend significance
!
! trend - trend, the Theil-Sen estimate of linear trend
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_cdft_t(n, p, df, t)
!
!   REAL,    INTENT(IN   ) :: p, df
!   REAL,    INTENT(  OUT) :: t
!
! Routine to calculate the t-value given the one-sided probability
! and the degrees of freedom.
!
! Using the cumulative distribution function for the T distribution,
! calculate the t-values associated with one or more probabilities
! and degrees of freedom. Technically, this is the upper limit of
! integration of the t-density distribution.
!
! Variables:
!
! p  - the one-sided probability ( 0 <= p < 1 )
!
! df - the number of degrees of freedom
!
! t  - the t-value
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_cdft_p(t, df, p)
!
!   REAL,    INTENT(IN   ) :: t, df
!   REAL,    INTENT(  OUT) :: p
!
! Routine to calculate the one-sided probability given a t-value
! and the degrees of freedom.
!
! Using the cumulative distribution function for the T distribution,
! calculate the one-sided probability associated with one or more
! t-values and degrees of freedom. Technically, this is the integral
! from -infinity to t of the t-density distribution.
!
! Variables:
!
! t  - the t-value
!
! df - the number of degrees of freedom
!
! p  - the one-sided probability
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_student_t(t, df, p)
!
!   REAL,    INTENT(IN   ) :: t, df
!   REAL,    INTENT(  OUT) :: p
!
! Routine to calculate the two-tailed probability of the Student-t
! distribution.
!
! Variables:
!
! t  - the t-value
!
! df - the number of degrees of freedom
!
! p  - the two-tailed probability
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_ttest( AVE1, VAR1, N1, AVE2, VAR2, N2, IFLAG, ALPHA, TVAL, IER )
!
!   INTEGER, INTENT(IN   ) :: N1, N2
!   REAL,    INTENT(IN   ) :: AVE1, VAR1, AVE2, VAR2
!   LOGICAL, INTENT(IN   ) :: IFLAG
!   REAL,    INTENT(  OUT) :: TVAL, ALPHA
!   INTEGER, INTENT(  OUT) :: IER
!
! Routine to calculate student t-statistic + prob
!
! nomenclature:
!
! input  ave1,var1,n1 - average, variance and size (sample 1)
! .      ave2,var2,n2 - average, variance and size (sample 2)
! .                     Ideally, n1 and n2 >=30
!
! output alpha        - level of significance
! .                     probability that a random variable
! .                     following the students t distribution
! .                     will exceed tval in absolute value.
! .      tval         - t-value
! .                     e.g.,if df=14. and tval=1.761 then alpha=0.10.
! .                          for a 2 tailed test alpha=0.10 (or 10%)
! .                          means that the critical region has 5%
! .                          in each tail. note: some users set
! .                                  prob = 1.-alpha
! .                          upon return to the calling program.
! .      iflag        - set to False if population variances are equal
! .                     set to True if population variances are unequal
! .      ier          - error code
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_ftest( VAR1, N1, VAR2, N2, ALPHA, IER )
!
!   INTEGER, INTENT(IN   ) :: N1, N2
!   REAL,    INTENT(IN   ) :: VAR1, VAR2
!   REAL,    INTENT(  OUT) :: ALPHA
!   INTEGER, INTENT(  OUT) :: IER
!
! Routune to calculate student t-statistic + prob
!
! nomenclature:
!
! input  var1,n1      - variance and size (sample 1)
! .      var2,n2      - variance and size (sample 2)
!
! output alpha        - level of significance;
! .                     probability that a random variable
! .                     following the students t distribution
! .                     will exceed tval in absolute value.
! .      ier          - error code
! .                     ier.ne.0 then alpha=errval
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_rtest( R, N, PROB )
!
!   INTEGER, INTENT(IN   ) :: N
!   REAL,    INTENT(IN   ) :: R
!   REAL,    INTENT(  OUT) :: PROB
!
! nomenclature:
!
! Input
! .   r     - linear correlation coef
! .   n     - number of points used to calculate "r"
!
! Output
! .   prob  - calculated significance [0. < prob < 1.]
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_equiv_sample_size( X, NPTS, XMSG, SIGLVL, NEQV )
!
!   INTEGER, INTENT(IN   ) :: NPTS
!   REAL,    INTENT(IN   ) :: X(NPTS)
!   REAL,    INTENT(IN   ) :: XMSG, SIGLVL
!   INTEGER, INTENT(  OUT) :: NEQV
!
! This assumes a red-noise process [r1>0.]
!
! nomenclature:
!
! Input
! .   x      - series
! .   npts   - number of pts
! .   xmsg   - missing code
! .   siglvl - significance level (eg: 0.05) at which the lag-1
! .            autocorrelation is to be tested.
!
! Output
! .   neqv   - Number of independent samples
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_esacr( x, npts, xmsg, mxlag, acr, ier )
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(1:npts)
!   REAL,    INTENT(IN   ) :: xmsg
!   INTEGER, INTENT(IN   ) :: mxlag
!   REAL,    INTENT(  OUT) :: acr(0:mxlag)
!   INTEGER, INTENT(  OUT) :: ier
!
! this routine will estimate the autocorrelations for the input vector
! .   x with missing data.
!
! arguments :
! .   x        - input vector
! .   npts     - length of vector x
! .   xmsg     - missing code: if no msg values set to some number
! .                            which will not be encountered.
! .   mxlag    - max lag to be estimated  [0 <= mxlag <= npts/4 ]
! .   acr      - sample autocorrelations [vector of length .ge. (mxlag+1) ]
! .   ier      - if (ier.ne.0) an error has occurred
!
! note :  uncalculated quantities are set to xmsg
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_esacv( x, npts, xmsg, mxlag, acv, ier )
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(1:npts)
!   REAL,    INTENT(IN   ) :: xmsg
!   INTEGER, INTENT(IN   ) :: mxlag
!   REAL,    INTENT(  OUT) :: acv(0:mxlag)
!   INTEGER, INTENT(  OUT) :: ier
!
! this routine will estimate the autocovariances for the input vector
! .   x with missing data.
!
! arguments :
! .   x        - input vector
! .   npts     - length of vector x
! .   xmsg     - missing code: if no msg values set to some number
! .                            which will not be encountered.
! .   mxlag    - max lag to be estimated  [0 <= mxlag <= npts/4 ]
! .   acr      - sample autocovariances [vector of length .ge. (mxlag+1) ]
! .   ier      - if (ier.ne.0) an error has occurred
!
! note :  uncalculated quantities are set to xmsg
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_esccr( x, y, npts, xmsg, ymsg, mxlag, ccr, ier )
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(1:npts), y(1:npts)
!   REAL,    INTENT(IN   ) :: xmsg, ymsg
!   INTEGER, INTENT(IN   ) :: mxlag
!   REAL,    INTENT(  OUT) :: ccr(0:mxlag)
!   INTEGER, INTENT(  OUT) :: ier
!
! this routine will estimate the crosscorrelations (ccr) for the input
! .   series x and y. missing data is allowed.
!
! .   to get the (+) and (-) crosscorrelations two calls must be made.
! .   the first with the calling sequence above and the second with
! .   the x and y series reversed (also the other arguments).
!
! arguments :
! .   x,y      - input vectors with which the calculations are to take place.
! .   npts     - length of vectors x and y
! .   xmsg,ymsg- missing code: if no msg values set to some number
! .                            which will not be encountered.
! .              xmsg will be used to fill missing values
! .   mxlag    - max lag correlation to be estimated  [0 <= mxlag <= npts/4 ]
! .   ccr      - sample cross-correlations [vector of length .ge. (mxlag+1) ]
! .   ier      - if (ier.ne.0) an error has occurred
!
! note : uncalculated quantities are set to xmsg
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_esccv( x, y, npts, xmsg, ymsg, mxlag, ccv, ier )
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(1:npts), y(1:npts)
!   REAL,    INTENT(IN   ) :: xmsg, ymsg
!   INTEGER, INTENT(IN   ) :: mxlag
!   REAL,    INTENT(  OUT) :: ccv(0:mxlag)
!   INTEGER, INTENT(  OUT) :: ier
!
! this routine will estimate the crosscovariances (ccv) for the input
! .   series x and y. missing data is allowed.
!
! .   to get the (+) and (-) crosscovariances two calls must be made.
! .   the first with the calling sequence above and the second with
! .   the x and y series reversed (also the other arguments).
!
! arguments :
! .   x,y      - input vectors with which the calculations are to take place.
! .   npts     - length of vectors x and y
! .   xmsg,ymsg- missing code: if no msg values set to some number
! .                            which will not be encountered.
! .              xmsg will be used to fill missing values
! .   mxlag    - max lag covariance to be estimated  [0 <= mxlag <= npts/4 ]
! .   ccv      - sample cross-covariances [vector of length .ge. (mxlag+1) ]
! .   ier      - if (ier.ne.0) an error has occurred
!
! note : uncalculated quantities are set to xmsg
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_escorc( x, y, npts, xmsg, ymsg, ccr, ier )
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts), y(npts)
!   REAL,    INTENT(IN   ) :: xmsg, ymsg
!   REAL,    INTENT(  OUT) :: ccr
!   INTEGER, INTENT(  OUT) :: ier
!
! this routine will estimate the crosscorrelation (ccr) for the input
! .   series x and y. missing data is allowed.
!
! arguments :
! .   x,y      - input vectors with which the calculations are to take place.
! .   npts     - length of vectors x and y
! .   xmsg,ymsg- missing code: if no msg values set to some number
! .                            which will not be encountered.
! .              xmsg will be used to fill missing values
! .   ccr      - cross-correlation at lag 0
! .   ier      - if (ier.ne.0) an error has occurred
!
! note : uncalculated quantities are set to xmsg
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_escovc( x, y, npts, xmsg, ymsg, ccv, ier )
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: x(npts), y(npts)
!   REAL,    INTENT(IN   ) :: xmsg, ymsg
!   REAL,    INTENT(  OUT) :: ccv
!   INTEGER, INTENT(  OUT) :: ier
!
! this routine will estimate the crosscovariance (ccv) for the input
! .   series x and y. missing data is allowed.
!
! arguments :
! .   x,y      - input vectors with which the calculations are to take place.
! .   npts     - length of vectors x and y
! .   xmsg,ymsg- missing code: if no msg values set to some number
! .                            which will not be encountered.
! .              xmsg will be used to fill missing values
! .   ccv      - cross-covariance at lag 0
! .   ier      - if (ier.ne.0) an error has occurred
!
! note : uncalculated quantities are set to xmsg
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_lspoly( M, X, Y, WGT, N, COEF )
!
!   INTEGER, INTENT(IN   ) :: M
!   REAL,    INTENT(IN   ) :: X(M), Y(M), WGT(M)
!   INTEGER, INTENT(IN   ) :: N
!   REAL,    INTENT(  OUT) :: COEF(N)
!
! Routine to calculate a set of coefficients for a weighted least
! squares polynomial fit to the given data.
!
! M:    the number of data points.
!       M must be greater than or equal to N.
!
! X:    a array with dimension at least M contains the
!       abscissa values of the data points.
!
! Y:    a array with dimension at least M contains the
!       ordinate values of the data points.
!
! WGT:  a array with dimension at least M contains the
!       weights for a weighted least squares model.  if no
!       weighting is desired, the elements of wGT should be set to 1.0.
!
! N:    the number of coefficients desired (i.e., N-1 will be the
!       degree of the polynomial).  Due to the computational method
!       used, N should be less than or equal to five.
!
! COEF: a array with dimension at least N contains the
!       coefficients for the polynomial.
!       COEF(1) will contain the constant term.
!
! Given a set of data (X(i),Y(i)), i = 1,...,M, ng_lspoly calculates
! a set of coefficients for a weighted least squares polynomial fit
! to the given data. It is necessary that the number of data points)
! be greater than N (the number of coefficients).
!
! Accuracy: for lower order polynomials (N .le. 5), ng_lspoly can be
! expected to give satisfactory results.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_dtrend( x, npts, slope, yint )
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(INOUT) :: x(npts)
!
!   REAL, INTENT(OUT), OPTIONAL :: slope, yint
!
! Routine to estimate and remove the least squares "linear" trend
!
! x        - series to be detrended
!
! npts     - length of vector x
!
! slope    - slope (trend ... regression coef) of the regression line
!
! yint     - y-intercept of the regression line
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_dtrend_quadratic( x, npts, coeff )
!
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(INOUT) :: x(npts)
!
!   REAL, INTENT(OUT), OPTIONAL :: coeff(3)
!
! Routine to estimate and remove the least squares quadratic trend
!
! x        - series to be detrended
!
! npts     - length of vector x
!
! coeff    - coefficients of the least squares quadratic
!            coeff(1)  constant
!            coeff(2)  coef of first power
!            coeff(3)  coef of second power
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_dtrend_msg( x, y, npts, xmsg, ymsg, iopt, ydt, slope, yint )
!
!   INTEGER, INTENT(IN   ) :: npts, iopt
!   REAL,    INTENT(IN   ) :: x(npts), y(npts), xmsg, ymsg
!   REAL,    INTENT(  OUT) :: ydt(npts)
!
!   REAL, INTENT(OUT), OPTIONAL :: slope, yint
!
! this routine will calculate the least squares "slope" and "y-intercept"
! .   remove the trend.
! .   (a) missing data are allowed.
! .   (b) data need not be equally spaced in "x"
!
! .   yLine = slope*y + yint
! .   ydt   = y - yLine
!
! arguments :
!
! .   x,y       - input vectors
!
! .   npts      - length of vectors x and y
!
! .   xmsg/ymsg - missing code: if no msg values set to some number
! .                             which will not be encountered.
! .               ymsg will be used to fill missing values
!
! .   iopt      - =1: (True)  Return ydt with the mean removed
! .               =0: (Flase) do not remove the mean
!
! .   ydt       - detrended series
! .               this could be "y" if original series not needed
!
! .   slope     - slope (trend ... regression coef)
!
! .   yint      - y-intercept of the INPUT series
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_taper( n, x, p, iopt )
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(INOUT) :: x(n)
!   REAL,    INTENT(IN   ) :: p
!   INTEGER, INTENT(IN   ) :: iopt
!
! Routine to apply split-cosine-bell tapering to the series x.
!
! This is used prior to performing a fast fourier transform (FFT) to
! a series that is not cyclic. It reduces the leakage from strong
! spectral peaks.
!
! Variables:
!
!   n    - Series length
!
!   x    - (IN)  Series to be tapered (tapering done in place)
!                **missing data not allowed**
!          (OUT) Tapered series
!
!   p    - The proportion (0.0<=p<=1.0) of the time series to be
!          tapered. Typically, p = 0.1 (corresponding to 10% of
!          the series).
!
!   iopt - iopt=0 taper to series mean
!          iopt=1 means *force* taper to 0.0
!          Acts like iopt=0 for the case of iopt not equal to 0 or 1
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_specx_anal( x, nx, iopt, jave, pct, scl, spcx, frq,&
!                           df, bw, xavei, xvari, xvaro, xlag1, xslope)
!
!   INTEGER, INTENT(IN   ) :: nx, iopt, jave
!   REAL,    INTENT(IN   ) :: x(nx), pct, scl
!   REAL,    INTENT(  OUT) :: spcx(nx/2+1), frq(nx/2+1)
!
!   REAL, INTENT(OUT), OPTIONAL :: df, bw, xavei, xvari, xvaro, xlag1, xslope
!
! Routine to perform a spectral analysis on the series x of length nx.
!
! input:
!
! x         - real series containing the data (unchanged upon return)
!
! nx        - number of points in x
!             nx need not be a power of 2 but the fft will run
!             optimally if nx is highly factorable.
!
! iopt      - detrending option
!             iopt<0 : do no detrending.
!             iopt=0 : remove series mean (minimum recommended option)
!             iopt=1 : remove the series mean and lst sqrs linear trend
!             iopt=2 : remove the series mean and lst sqrs quadratic trend
!                      know what you are doing before applying this option
!
! jave      - smoothing to be performed on the periodiogram
!             this should be an odd number (>=3) , if not, the
!             routine will force it to the next largest odd number.
!             jave=0 : do no smoothing
!                      spcx contains raw spectral estimates
!                      (periodogram)
!             jave>0 : average jave periodogram estimates together
!                      utilizing modified daniell smoothing (good
!                      stability but may lead to large bias ).
!                      all weights are 1/jave except wgt(1) and
!                      wgt(jave) which are 1/(2*jave). this is
!                      the recommended option.
!
! pct       - % of the series to be tapered [0.<=pct>=1.]
!             if pct=0. no tapering will be done
!             if pct=1. the whole series is effected
!             a pct of 0.10 is common. tapering should always be
!             done unless the data is strictly periodic.
!
! scl       - scaling factor (there are 4 special cases.)
!             scl = -1.: spcx estimates are scaled so that the area
!                        under the curve [ s(f)*df ] equals one.
!             scl = 0. : spcx estimates are scaled so that the sum
!                        of the spectral estimates is the same as
!                        the variance of the detrended (optional)
!                        input series
!             scl = 1. : spcx estimates are as calculated  by g13cbf
!             scl = 2. : spcx estimates are scaled so that the area
!                        under the curve [ s(f)*df ] equals the
!                        variance of the detrended (optional)
!                        input series.
!             scl= 2 or -1. is recommended
!
! output:
!
! frq       - frequency vector of length (nx/2+1)
!
! spcx      - spectrum : vector of length (nx/2+1)
!             spcx(1)      - this will be the **mean* of the
!                            detrended-tapered series. it
!                            is not a variance. it is not the
!                            spectral estimate at freq = 0
!             spcx(2)      - spectral estimate at freq = 1/nx
!             spcx(3)      - spectral estimate at freq = 2/nx
!                          .
!             spcx(nx/2+1) - spectral estimate at freq = 0.5
!
! optional output:
!
! df:     the degrees of freedom
!
! bw:     the spectral band width.
!
! xavei:  the average of the x series on input.
!
! xvari:  the variance of the x series on input.
!
! xvaro:  the variance of the x series after detrending.
!
! xlag1:  the lag-one autocorrelation of the x series after detrending.
!
! xslope: the least-squares slope per time interval of linear trend
!         (if iopt = 1) of the x series.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_specxy_anal( x, y, n, iopt, jave, pct, scl,&
!                            frq, spcx, spcy, cospc, quspc, coher, phase,&
!                            df, bw, coherp,&
!                            xavei, xvari, xvaro, xlag1, xslope,&
!                            yavei, yvari, yvaro, ylag1, yslope)
!   IMPLICIT NONE
!
!   INTEGER, INTENT(IN   ) :: n, iopt, jave
!   REAL,    INTENT(IN   ) :: x(n), y(n), pct, scl
!   REAL,    INTENT(  OUT) :: frq(n/2+1), spcx(n/2+1), spcy(n/2+1)
!   REAL,    INTENT(  OUT) :: cospc(n/2+1), quspc(n/2+1), coher(n/2+1), phase(n/2+1)
!
!   REAL, INTENT(OUT), OPTIONAL :: df, bw, coherp(4)
!   REAL, INTENT(OUT), OPTIONAL :: xavei, xvari, xvaro, xlag1, xslope
!   REAL, INTENT(OUT), OPTIONAL :: yavei, yvari, yvaro, ylag1, yslope
!
! Routine to perform a spectral/cross spc analysis on series x and y.
!
! input:
!
! x         - real series containing the data (unchanged upon return)
!
! y         - real series containing the data (unchanged upon return)
!
! n         - number of points in x and y (need not be a power of 2)
!
! iopt      - detrending option
!             iopt<0 : do no detrending.
!             iopt=0 : remove series mean (minimum recommended option)
!             iopt=1 : remove the series mean and lst sqrs linear trend
!             iopt=2 : remove the series mean and lst sqrs quadratic trend
!                      know what you are doing before applying this option
!
! jave      - no. of spectral estimates to be averaged
!
! pct       - % of the series to be tapered [0.<=pct>=1.]
!             if pct=0. no tapering will be done
!             if pct=1. the whole series is effected
!             a pct of 0.10 is common. tapering should always be
!             done unless the data is strictly periodic.
!
! scl       - scaling factor (there are 4 special cases.)
!             scl = -1.: spcx estimates are scaled so that the area
!                        under the curve [ s(f)*df ] equals one.
!             scl = 0. : spcx estimates are scaled so that the sum
!                        of the spectral estimates is the same as
!                        the variance of the detrended (optional)
!                        input series
!             scl = 1. : spcx estimates are as calculated  by g13cbf
!             scl = 2. : spcx estimates are scaled so that the area
!                        under the curve [ s(f)*df ] equals the
!                        variance of the detrended (optional)
!                        input series.
!
! output:
!
! frq       - frequency vector of length (nx/2+1)
!
! spcx,spcy - spectrum vector of length (n/2+1) for x and y series
!             spcx(1)     - spectral estimate at freq = 0 (ignore)
!             spcx(n/2+1) - spectral estimate at freq = 0.5
!
! cospc     - cospectrum : vector of length (n/2+1)
!             this is the real part of the cross spectrum. it
!             measures the extent to which there are oscillations
!             with the same phase in the two series (or with
!             opposite sign ,i.e. , with a phase shift of half a
!             cycle). In other words : it measures the
!             contribution of different frequencies to the total
!             cross-covariance at zero lag.
!
! quspc     - quadrature spectrum  : vector of length (n/2+1)
!             this is the imaginary part of the cross spectrum. it
!             measures the extent to which there are oscillations
!             with a phase difference of a quarter cycle in either
!             direction. i.e., it measures the contribution of
!             different frequencies to the total cross-covariance
!             of the series when all harmonics of one series
!             are delayed a quarter cycle relative to the other
!             relative to the other series.
!
! coher     - coherence squared  : vector of length (n/2+1)
!             this is analogous to the square of the correlation
!             coef except that the coherence squared is a
!             function of frequency.
!
! phase     - phase (in degrees)  : vector of length (n/2+1)
!             A positive phase indicates that x leads y.
!
! optional output:
!
! df        - the degree of freedom
!
! bw        - the spectral bandwidth.
!
! coherp    - array of length 4 containing the coherence corresponding to
!             the 90, 95, 99, and 99.9% levels.
!
! xavei     - the average of the x series on input.
!
! xvari     - the variance of the x series on input.
!
! xvaro     - the variance of the x series after detrending.
!
! xlag1     - the lag-one autocorrelation of the x series after detrending.
!
! xslope    - the least-squares slope per time interval of linear trend
!             (if iopt = 1) of the x series.
!
! yavei     - the average of the y series on input.
!
! yvari     - the variance of the y series on input.
!
! yvaro     - the variance of the y series after detrending.
!
! ylag1     - the lag-one autocorrelation of the y series after detrending.
!
! yslope    - the least-squares slope per time interval of linear trend
!             (if iopt = 1) of the y series.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_specx_ci( nspc, spcx, frq, xlag1, df, plow, phign, splt )
!
!   INTEGER, INTENT(IN   ) :: nspc
!   REAL,    INTENT(IN   ) :: spcx(nspc), frq(nspc)
!   REAL,    INTENT(IN   ) :: xlag1, df, plow, phign
!   REAL,    INTENT(  OUT) :: splt(nspc,4)
!
! Calculate the theoretical Markov spectrum and lower and upper
! confidence curves using the lag1 autocorrelation returned by the
! NCL function "specx_anal"
!
! nspc  - number of spectral, size or array spcx and frq
!
! spcx  - spectrum returned by "specx_anal", vector of length nspc
!
! frq   - frequency returned by "specx_anal", vector of length nspc
!
! xlag1 - lag-one autocorrelation returned by "specx_anal"
!
! df    - degrees of freedom returned by "specx_anal"
!
! plow  - lower confidence limit (0.0 < plow < 1.)
!         a typical value is 0.05
!
! phigh - upper confidence limit (0.0 < phigh< 1.)
!         a typical value is 0.95
!
! splt  - returned 2D array containing 4 curves
!         splt(:,1) - input spectrum
!         splt(:,2) - Markov "Red Noise" spectrum
!         splt(:,3) - lower confidence bound for Markov
!         splt(:,4) - upper confidence bound for Markov
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_specxy_ci( nspc, spcx, frq, xlag1, df, plow, phign, splt )
!
!   INTEGER, INTENT(IN   ) :: nspc
!   REAL,    INTENT(IN   ) :: spcx(nspc), frq(nspc)
!   REAL,    INTENT(IN   ) :: xlag1, df, plow, phign
!   REAL,    INTENT(  OUT) :: splt(nspc,4)
!
! Calculate the theoretical Markov spectrum and lower and upper
! confidence curves using the lag1 autocorrelation returned by the
! NCL function "specxy_anal"
!
! nspc  - number of spectral, size or array spcx and frq
!
! spcx  - spectrum returned by "specxy_anal", vector of length nspc
!
! spcy  - spectrum returned by "specxy_anal", vector of length nspc
!
! frq   - frequency returned by "specxy_anal", vector of length nspc
!
! xlag1 - lag-one autocorrelation returned by "specxy_anal"
!
! ylag1 - lag-one autocorrelation returned by "specxy_anal"
!
! df    - degrees of freedom returned by "specxy_anal"
!
! plow  - lower confidence limit (0.0 < plow < 1.)
!         a typical value is 0.05
!
! phigh - upper confidence limit (0.0 < phigh< 1.)
!         a typical value is 0.95
!
! splt  - returned 2D array containing 8 curves
!         splt(:,1) - input "x" spectrum
!         splt(:,2) - x: Markov "Red Noise" spectrum
!         splt(:,3) - x: lower confidence bound for Markov
!         splt(:,4) - x: upper confidence bound for Markov
!         splt(:,5) - input "y" spectrum
!         splt(:,6) - y: Markov "Red Noise" spectrum
!         splt(:,7) - y: lower confidence bound for Markov
!         splt(:,8) - y: upper confidence bound for Markov
!
!---------------------------------------------------------------------
!
! REAL FUNCTION ng_chiinv( p, df )
!
!   REAL, INTENT(IN) :: p, df
!
! Function (ng_chiinv) to calculate the upper limit of integration of
! a cumulative chi-square distribution function.
!
! p   - the integral from 0 to ng_chiinv [0 < p < 1]
!
! df  - the number of degrees of freedom of the chi-square distribution
!       (0, +infinity).
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_wavelet(n, y, mother, dt, param, s0, dj, jtot, npad,&
!                       noise, isigtest, siglvl, nadof, wave,&
!                       power, phase, mean, stdev, lag1, r1, dof, scale,&
!                       period, gws, coi, fft_theor, signif, cdelta, psi0)
!
! Routine to calculate the wavelet transform of a time series and
! significance levels
!
!   INTEGER, INTENT(IN   ) :: n, jtot
!   REAL,    INTENT(IN   ) :: y(n)
!   INTEGER, INTENT(IN   ) :: mother, npad, noise, isigtest
!   REAL,    INTENT(IN   ) :: dt, param, s0, dj, siglvl, nadof(2)
!   REAL,    INTENT(  OUT) :: wave(n,jtot,2)
!
!   REAL, OPTIONAL, INTENT(OUT) :: power(n,jtot)
!   REAL, OPTIONAL, INTENT(OUT) :: phase(n,jtot)
!   REAL, OPTIONAL, INTENT(OUT) :: mean
!   REAL, OPTIONAL, INTENT(OUT) :: stdev
!   REAL, OPTIONAL, INTENT(OUT) :: lag1
!   REAL, OPTIONAL, INTENT(OUT) :: r1
!   REAL, OPTIONAL, INTENT(OUT) :: dof(jtot)
!   REAL, OPTIONAL, INTENT(OUT) :: scale(jtot)
!   REAL, OPTIONAL, INTENT(OUT) :: period(jtot)
!   REAL, OPTIONAL, INTENT(OUT) :: gws(jtot)
!   REAL, OPTIONAL, INTENT(OUT) :: coi(n)
!   REAL, OPTIONAL, INTENT(OUT) :: fft_theor(jtot)
!   REAL, OPTIONAL, INTENT(OUT) :: signif(jtot)
!   REAL, OPTIONAL, INTENT(OUT) :: cdelta
!   REAL, OPTIONAL, INTENT(OUT) :: psi0
!
! Variables:
!
! n - the number of points in "y".
!
! y - the time series of length "n".
!
! mother = An integer giving the mother wavelet to use:
!
!          0 = 'Morlet'
!          1 = 'Paul'
!          2 = 'DOG' (derivative of Gaussian)
!
!          If mother < 0 or > 2, then the default is 'Morlet'.
!          (Most commonly, mother = 0.)
!
! dt - The amount of time between each y value; i.e. the sampling time.
!      (Most commonly, dt = 1.0.)
!
! param - The mother wavelet parameter. If param < 0, then the default is used:
!
!         For 'Morlet' this is k0 (wavenumber), default is 6.
!         For 'Paul' this is m (order), default is 4.
!         For 'DOG' this is m (m-th derivative), default is 2.
!
! s0 - The smallest scale of the wavelet, which is typically is equal to 2*dt.
!
!      Note: for accurate reconstruction and variance computation,
!      set s0 = dt for Morlet; s0 = dt/4 for Paul. (Most commonly, s0 = 2*dt.)
!
! dj - The spacing between discrete scales, which is typically equal to 0.25.
!
!      A smaller value will give better scale resolution, but will be slower.
!      (Most commonly, dj = 0.25.)
!
! jtot - The integer number of scales. Scales range from s0 up to s0*2^[(jtot-1)*dj].
!
!        Most commonly, jtot is equal to:
!
!        1 + floattointeger(((log10(N*dt/s0))/dj)/log10(2.))
!
! npad - The total number of points (including padding) to use for the wavelet transform.
!        Typically, this is some power of 2. It must be greater or equal to N.
!        If npad > N, then zeroes are padded onto the end of the time series.
!        (Most commonly, npad = N [i.e. no padding].)
!
! noise - A value of 0 means use a white noise background for significance testing.
!         A value of 1 means use a red noise background for significance testing.
!         (Most commonly, noise = 1.)
!
! isigtest - A value of 0 means do a regular chi-square test. A value of 1 means
!            do a "time-average" test on the global wavelet spectrum.
!
! siglvl - The significance level to use. (Most commonly, siglvl = 0.95.)
!
! nadof - Currently ignored (set to zero).
!
! wave - returned three-dimensional array (call it wave), dimensioned (n,jtot,2).
!
!        wave will contain the real (:,:,1) and imaginary parts (:,:,2)
!        of the wavelet transform, versus time and scale
!
!---------
!
! This subroutine is an interface to the wavelet software written by
! Christopher Torrence and Gilbert P. Compo, University of Colorado.
! The original software is available from:
!
!    http://paos.colorado.edu/research/wavelets/
!
! This site provides Fortran, IDL and Matlab codes, including examples.
!
! The user should read the following reference:
!
!    Torrence, C. and G. P. Compo, 1998: A Practical Guide to Wavelet Analysis.
!    Bull. Amer. Meteor. Soc., 79, 61-78.
!    doi: http://dx.doi.org/10.1175/1520-0477(1998)079<0061:APGTWA>2.0.CO;2
!
! This will clarify the terminology used by the software.
!
! Note: please acknowledge the use of this software in any publications:
!
!    "Wavelet software was provided by C. Torrence and G. Compo, and is
!    available at the URL: http://paos.colorado.edu/research/wavelets/".
!
!---------
!
! The following optional arguments are returned as attributes of wave:
!
! power - the squared sum of the real and imaginary parts of wave.
!
!         The power spectrum = wave(:,:,1)^2 + wave(:,:,2)^2
!
! phase - the phases (degrees) of wave:
!
!         phase = atan2(wave(:,:,1),wave(:,:,2))  (*57.29 for degrees)
!
! mean - the mean of the input series.
!
! stdev - the standard deviation of the input series.
!
! lag1 - the lag-1 autocorrelation of the input series.
!
! r1 - If noise = 1, this contains the lag-1 autocorrelation of the input series.
!      Otherwise, r1 = 0.0. This is the value used in the significance test.
!
! dof - the degrees-of-freedom for significance test.
!
! scale - the wavelet scales that were used.
!
! period - the "Fourier" periods (in time units) corresponding to "scale".
!
! gws - the global wavelet spectrum.
!
! coi - the e-folding factor used for the cone of influence.
!
! fft_theor - the theoretical red-noise spectrum versus scale.
!
!             If isigtest = 2, then fft_theor(1) = the average spectrum from
!             S1-->S2, and fft_theor(2...jtot) = 0.0.
!
! signif - the significance levels versus scale.
!
! cdelta - the constant "Cdelta" for the mother wavelet (Table 2 of reference).
!
! psi0 - the constant "psi(0)" for the mother wavelet.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_pdfx( nx, x, xmsg, nbins, bin_bounds, pdf )
!   INTEGER, INTENT(IN   ) :: nx, nbins
!   REAL,    INTENT(IN   ) :: x(nx), xmsg, bin_bounds(0:nbins)
!   REAL,    INTENT(  OUT) :: pdf(nbins)
!
! Routine to generate a univariate probability density distribution (PDF).
!
! nx:         Size of array x
!
! x:          Array of size (nx) containing the data used to generate PDF
!
! xmsg:       Missing value of array x
!
! nbins:      Number of bins to use
!
! bin_bounds: Array of size (nbins +1) containing the boundaries of each bin.
!
! pdf:        Probability density distribution (PDF), array of size nbin.
!             The PDF units are percent [%].
!
!---------------------------------------
! Calculation of bin_bounds
!---------------------------------------
!
! bin_nice      - "nice" bin boundary values and spacing will be calculated.
!
! bin_n         - the number of bins used.
! bin_spacing   - the spacing of the bins used.
! bin_bound_min - the minimum boundary bin value.
! bin_bound_max - the maximum boundary bin value.
! bin_center    - a one-dimensional array of size nbins containing the
!                 center points of each bin. For plotting these can be
!                 used as the "x" [abscissa].
! bin_bounds    - a one-dimensional array of size (nbins +1) containing
!                 the boundaries of each bin.
!
! !-----------------
!
! IF( .NOT. bin_nice ) THEN
!   ! Manual mode
!   numbin = ... (Number of bins to use, must be greater than 2)
!   binmin = ... (Minmun value for the bin boundary)
!   binmax = ... (Maxmun value for the bin boundary)
! ELSE
!   ! Auto mode
!   maxbin = ... (Maximum number of bins desired, > 2)
! END IF
!
! !-------
!
! IF( .NOT. bin_nice ) THEN
!   bin_bound_min = binmin
!   bin_bound_max = binmax
!   bin_n         = numbin
!   bin_spacing   = (bin_bound_max-bin_bound_min)/REAL(bin_n)
! ELSE
!   ! calculates "nice" values for endpoints and spacing
!   outside = .FALSE.
!   CALL ng_nice_mnmxintvl( MINVAL(x), MAXVAL(x), outside, bin_bound_min, bin_bound_max, bin_spacing )
!   bin_n = NINT((bin_bound_max-bin_bound_min)/bin_spacing)
! ELSE
! END IF
!
! ALLOCATE( bin_bounds(0:bin_n), bin_center(bin_n) )
!
! bin_bounds = bin_bound_min + REAL((/(i,i=0,bin_n)/))*bin_spacing
! bin_center = 0.5*(bin_bounds(0:nbins-1)+bin_bounds(1:nbins))
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_pdfxy( nxy, x, y, xmsg, ymsg, nbinx, nbiny, binx_bounds, biny_bounds, pdf )
!   INTEGER, INTENT(IN   ) :: nxy, nbinx, nbiny
!   REAL,    INTENT(IN   ) :: x(nxy), xmsg, binx_bounds(0:nbinx)
!   REAL,    INTENT(IN   ) :: y(nxy), ymsg, biny_bounds(0:nbiny)
!   REAL,    INTENT(  OUT) :: pdf(nbinx,nbiny)
!
! Routine to generate a joint probability density distribution (PDF).
!
! nxy:         Size of array x and y
!
! x/y:         Array of size (nxy) containing the data used to generate PDF
!
! xmsg/ymsg:   Missing value of array x/y
!
! nbinx/nbiny: Number of bins to use for x/y
!
! binx_bounds: Array of size (nbinx+1) containing the x-boundaries of each bin.
!
! biny_bounds  Array of size (nbiny+1) containing the y-boundaries of each bin.
!
! pdf:         Probability density distribution (PDF), array of size (nbinx,nbiny).
!              The PDF units are percent [%].
!
!---------------------------------------
! Calculation of bin_bounds
!---------------------------------------
!
! bin_nice      - "nice" bin boundary values and spacing will be calculated.
!
! bin_n         - the number of bins used.
! bin_spacing   - the spacing of the bins used.
! bin_bound_min - the minimum boundary bin value.
! bin_bound_max - the maximum boundary bin value.
! bin_center    - a one-dimensional array of size nbins containing the
!                 center points of each bin. For plotting these can be
!                 used as the "x" [abscissa].
! bin_bounds    - a one-dimensional array of size (nbins +1) containing
!                 the boundaries of each bin.
!
! !-----------------
!
! IF( .NOT. bin_nice ) THEN
!   ! Manual mode
!   numbin = ... (Number of bins to use, must be greater than 2)
!   binmin = ... (Minmun value for the bin boundary)
!   binmax = ... (Maxmun value for the bin boundary)
! ELSE
!   ! Auto mode
!   maxbin = ... (Maximum number of bins desired, > 2)
! END IF
!
! !-------
!
! IF( .NOT. bin_nice ) THEN
!   bin_bound_min = binmin
!   bin_bound_max = binmax
!   bin_n         = numbin
!   bin_spacing   = (bin_bound_max-bin_bound_min)/REAL(bin_n)
! ELSE
!   ! calculates "nice" values for endpoints and spacing
!   outside = .FALSE.
!   CALL ng_nice_mnmxintvl( MINVAL(x), MAXVAL(x), outside, bin_bound_min, bin_bound_max, bin_spacing )
!   bin_n = NINT((bin_bound_max-bin_bound_min)/bin_spacing)
! ELSE
! END IF
!
! ALLOCATE( bin_bounds(0:bin_n), bin_center(bin_n) )
!
! bin_bounds = bin_bound_min + REAL((/(i,i=0,bin_n)/))*bin_spacing
! bin_center = 0.5*(bin_bounds(0:nbins-1)+bin_bounds(1:nbins))
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_pdfxy_conform( nx, x, xmsg, ny, y, ymsg, nbinx, nbiny, binx_bounds, biny_bounds, pdf )
!   INTEGER, INTENT(IN   ) :: nx
!   REAL,    INTENT(IN   ) :: x(nx), xmsg
!   INTEGER, INTENT(IN   ) :: ny
!   REAL,    INTENT(IN   ) :: y(ny), ymsg
!   INTEGER, INTENT(IN   ) :: nbinx, nbiny
!   REAL,    INTENT(IN   ) :: binx_bounds(0:nbinx), biny_bounds(0:nbiny)
!   REAL,    INTENT(  OUT) :: pdf(nbinx,nbiny)
!
! Routine to generate a joint probability density distribution (PDF).
! An interface to ng_pdfxy that allows the input arrays (x and y) to
! be different sizes.
!
! nx/ny        Size of arrays x/y
!
! x/y:         Arrays containing the data used to generate bivariate PDF
!
! xmsg/ymsg:   Missing value of array x/y
!
! nbinx/nbiny: Number of bins to use for x/y
!
! binx_bounds: Array of size (nbinx+1) containing the x-boundaries of each bin.
!
! biny_bounds  Array of size (nbiny+1) containing the y-boundaries of each bin.
!
! pdf:         Probability density distribution (PDF), array of size (nbinx,nbiny).
!              The PDF units are percent [%].
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_center_finite_diff(npts, q, r, qmsg, rcyc, dqdr)
!   INTEGER, INTENT(IN   ) :: npts
!   REAL,    INTENT(IN   ) :: q(npts), r(npts), qmsg
!   LOGICAL, INTENT(IN   ) :: rcyc
!   REAL,    INTENT(  OUT) :: dqdr(npts)
!
! perform a centered finite difference:
! .   dq/dr ==> partial(q)/partial(r) ==>
! .             dqdr(n) = (q(n+1)-q(n-1))/(r(n+1)-r(n-1))
!
! Nomenclature:
! .   npts  - number of points
! .   q     - input vector [variable to be differenced]
! .   r     - input vector [spatial or temporal coordinates]
! .   qmsg  - msg value for q
! .   rcyc  - =.TRUE. if data are cyclic in the "r" coordinate
! .   dqdr  - result
!
!=====================================================================
! Math and Statistics - Empirical orthogonal functions
!=====================================================================
!
! SUBROUTINE ng_eofunc(npts, ntim, data, dmsg, neval, jopt, evec, eval, epcv, evec_ts)
! SUBROUTINE ng_eofunc_ts(npts, ntim, data, dmsg, neval, evec, jopt, evec_ts, ts_mean)
! SUBROUTINE ng_eof2data(neval, npts, ntim, ev, evts, xmsg, x)
! SUBROUTINE ng_eofunc_varimax(npts, neval, evec, eval, epcv, emsg, iopt, evec_rot, rot_var, rot_pcv)
! SUBROUTINE ng_eofunc_varimax_reorder(npts, neval, evec_rot, rot_pcv, rot_var)
! SUBROUTINE ng_eofunc_north(neval, eval, ntim, prinfo, sig)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_eofunc(npts, ntim, data, dmsg, neval, jopt, evec,&
!                      eval, epcv, evec_ts)
!
!   INTEGER, INTENT(IN   ) :: npts, ntim
!   REAL,    INTENT(IN   ) :: data(npts,ntim), dmsg
!   INTEGER, INTENT(IN   ) :: neval, jopt
!   REAL,    INTENT(  OUT) :: evec(npts,neval)
!   REAL,    INTENT(  OUT), OPTIONAL :: eval(neval), epcv(neval),&
!                                       evec_ts(ntim,neval)
!
! Routine to generate the Empirical Orthogonal Functions (EOFs) for
! a given time-space data set.
!
! Note: although the routine is set up as if the data is exactly two
! dimensional (X,T), that you can compute the EOFs of 3-D (X,Y,T)
! fields simply by concatenating the data along the X,Y axes into one
! big 2-D array and then computing the EOFs of that 2-D array).  The
! "typical" normalization is applied, i.e., the magnitude of the
! eigenvectors is scaled to be equal to 1.
!
! Variables:
!
!   npts    - number of space (station/grid) points
!
!   ntim    - number of time points (steps)
!
!   data    - data to compute the EOFs.
!
!   dmsg    - missing value of array data
!
!   neval   - number of eigenvaluse (EOFs) to compute. (This is usually
!             less than or equal to the minimum number of
!             observations ntim or number of variables npts.)
!
!   jopt    - if =0, then compute using covariance matrix;
!             if =1, then compute using correlation matrix.
!
!   evec    - the computed eigenvectors of the data,
!             the most important returned first.
!
!   eval    - the computed eigenvalues of the data,
!             the largest returned first.
!
!   epcv    - the percent of variance explained by each mode.
!
!   evec_ts - the principal components of the data (i.e., the
!             time series (mean remived) of the amplitudes
!             associated with each eigenvalue in an EOF).
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_eofunc_ts(npts, ntim, data, dmsg, neval, evec, jopt,&
!                         evec_ts, ts_mean)
!
!   INTEGER, INTENT(IN   ) :: npts, ntim
!   REAL,    INTENT(IN   ) :: data(npts,ntim), dmsg
!   INTEGER, INTENT(IN   ) :: neval
!   REAL,    INTENT(IN   ) :: evec(npts,neval)
!   INTEGER, INTENT(IN   ) :: jopt
!   REAL,    INTENT(  OUT) :: evec_ts(ntim,neval)
!   REAL,    INTENT(  OUT), OPTIONAL :: ts_mean(neval)
!
! Routine to calculate the time series of the amplitudes associated
! with each eigenvalue in an EOF. These amplitudes are also called
! principal components, expansion coefficients, scores, etc. They
! are derived via the dot product of the data and the EOF spatial
! patterns. The mean is subtracted from the value of each component
! time series.
!
! Variables:
!
!   npts    - number of space (station/grid) points
!
!   ntim    - number of time points (steps)
!
!   data    - data to compute the EOFs.
!
!   dmsg    - missing value of array data
!
!   neval   - number of eigenvalues
!
!   evec    - eigenvectors of the data (computed by ng_eofunc)
!
!   jopt    - =0 means covariance  was used to generate evec
!             =1 means correlation was used to generate evec
!
!   evec_ts - time series (means removed) of eof amplitudes
!             for each eigenvalue
!
!   ts_mean - the means removed from evec_ts
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_eof2data(neval, npts, ntim, ev, evts, xmsg, x)
!
!   INTEGER, INTENT(IN   ) :: neval, npts, ntim
!   REAL,    INTENT(IN   ) :: ev(npts,neval), evts(ntim,neval), xmsg
!   REAL,    INTENT(  OUT) :: x(npts,ntim)
!
! Routine to reconstruct a data set from EOFs and EOF time series.
! If the EOFs and EOF time series were calculated with ng_eofunc and
! ng_eofunc_ts, then you must use ng_eof2data to reconstruct the
! original data field.
!
! Variables:
!
! neval - the second dimension (number of eigen) of arrays ev and evts
!
! npts  - the first dimension (space) of array ev
!
! ntim  - the first dimension (time) of array evts
!
! ev    - A two-dimensional array containing the EOFs calculated
!         using ng_eofunc.
!
! evts  - A two-dimensional array containing the EOF time series
!         calculated using ng_eofunc_ts.
!
! xmsg  - missing code of arrays ev and evts
!
! x     - the reconstructed data array
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_eofunc_varimax(npts, neval, evec, eval, epcv, emsg, iopt,&
!                              evec_rot, rot_var, rot_pcv)
!
!   INTEGER, INTENT(IN   ) :: npts, neval
!   REAL,    INTENT(IN   ) :: evec(npts,neval), eval(neval), epcv(neval)
!   REAL,    INTENT(IN   ) :: emsg
!   INTEGER, INTENT(IN   ) :: iopt
!   REAL,    INTENT(  OUT) :: evec_rot(npts,neval)
!   REAL,    INTENT(  OUT), OPTIONAL :: rot_var(neval), rot_pcv(neval)
!
! Routine to rotate EOFs (eigenvectors) using the using Kaiser row
! normalization and the varimax criterion.
!
! Variables:
!
!   npts  - number of space points
!
!   neval - number of eigenvalues
!
!   evec  - normalized eigenvectors (computed from ng_eofunc)
!
!   eval  - eigenvalues (computed from ng_eofunc)
!
!   epcv  - percent variances (computed from ng_eofunc)
!
!   emsg  - missing value
!
!   iopt  - = 0: do nothing; use the normalized eigenvectors directly.
!           =+1: scale the normalized eigenvectors by the square root
!                of the associated eigenvalue and return "normalized"
!                rotated eigenvectors.
!           =-1: same as "+1" but returns the "scaled" rotated eigenvectors.
!
!   evec_rot - returned (normalized/scaled) rotated eigenvectors
!
!   rot_var  - variance of rotated eigenvectors
!
!   rot_pcv  - percent variance of rotated eigenvectors
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_eofunc_varimax_reorder(npts, neval, evec_rot, rot_pcv,&
!                                      rot_var)
!
!   INTEGER, INTENT(IN   ) :: npts, neval
!   REAL,    INTENT(INOUT) :: evec_rot(npts,neval), rot_pcv(neval)
!   REAL,    INTENT(INOUT), OPTIONAL :: rot_var(neval)
!
! Routine to reorder the results returned by ng_eofunc_varimax into
! descending order by percent variance explained.
!
! Variables:
!
!   npts     - number of space points
!
!   neval    - number of eigenvalues
!
!   evec_rot - rotated eigenvectors
!
!   rot_pcv  - percent variance of rotated eigenvectors
!
!   rot_var  - variance of rotated eigenvectors
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_eofunc_north(neval, eval, ntim, prinfo, sig)
!
!   INTEGER, INTENT(IN   ) :: neval
!   REAL,    INTENT(IN   ) :: eval(neval)
!   INTEGER, INTENT(IN   ) :: ntim
!   LOGICAL, INTENT(IN   ) :: prinfo
!   LOGICAL, INTENT(  OUT) :: sig(neval)
!
! Routine to evaluate eigenvalue separation by using North et al
! (MWR, 1982) equation 24.
!
! Variables:
!
!   neval  - size of array eval
!
!   eval   - eigenvalues to be tested (Actually, percent variances
!            associated with eigenvalue can also be used)
!
!   ntim   - maximum possible number of eigenvalues. Typically, in
!            climate applications, this is the number time steps.
!
!   prinfo - Print the calculated 'delta lambda', the eigenvalues,
!            the lower and upper test bounds and the 'separated
!            significance' (sig).
!
!   sig    - separated significance. .TRUE. means eigenvalues are
!            significantly separated.
!
! Reference:
!
!   North, G.R. et al (1982): Sampling Errors in the Estimation of
!   Empirical Orthogonal Functions. Mon. Wea. Rev., 110, 699-706.
!   doi: http://dx.doi.org/10.1175/1520-0493(1982)110<0699:SEITEO>2.0.CO;2
!
!=====================================================================
! Math and Statistics - Extreme values
!=====================================================================
!
! SUBROUTINE ng_extval_mlegev (n, x, xmsg, iopt, vals)
! SUBROUTINE ng_extval_mlegam (n, x, xmsg, iopt, vals)
! SUBROUTINE ng_extval_gev    (n, x, shape, scale, center,        iopt, pdf, cdf)
! SUBROUTINE ng_extval_gumbel (n, x, scale,        center,        iopt, pdf, cdf)
! SUBROUTINE ng_extval_frechet(n, x, shape, scale, center,        iopt, pdf, cdf)
! SUBROUTINE ng_extval_pareto (n, x, shape, scale, center, itype, iopt, pdf, cdf)
! SUBROUTINE ng_extval_weibull(n, x, shape, scale, center,        iopt, pdf, cdf)
! SUBROUTINE ng_extval_recurrence_table(n, time, x, dims, iopt, table)
! SUBROUTINE ng_extval_return_period(Tr, Pr, Nr)
! SUBROUTINE ng_extval_return_prob  (Tr, Nr, Pr)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_extval_mlegev(n, x, xmsg, iopt, vals)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n), xmsg
!   LOGICAL, INTENT(IN   ) :: iopt
!   REAL,    INTENT(  OUT) :: vals(6)
!
! Routine to estimate the shape, scale and location parameters for the
! Generalized Extreme-Value (GEV) distribution using Maximum-Likelihood
! Estimation (MLE).
!
! Variables:
!
! n      - size of array x
!
! x      - 1-d data array
!
! xmsg   - missing value of x
!
! iopt   - currently not used. set to .FALSE.
!
! vals   - the maximum-likelihood estimates (MLEs) of the parameters
!          of the generalized extreme value distribution (GEV) and
!          their standard errors. The parameters are: (i) shape,
!          (ii) location (aka, center), and (iii) scale.
!
!            vals(1) - center (location) of MLE
!            vals(2) - scale of MLE
!            vals(3) - shape of MLE
!            vals(4) - standard errors of center
!            vals(5) - standard errors of scale
!            vals(6) - standard errors of shape
!
! Note: Several sources and software packages use different conventions
! for the sign of the shape parameter.
!
! It is important to note that the 'center' (aka: location, shift)
! parameter is not the mean. However, it does represent the
! ‘center’ of the distribution. The 'scale' (aka, sigma, beta)
! parameter is not the standard deviation. However, it does govern
! the spread (size) of the deviations about the 'center'.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_extval_mlegam(n, x, xmsg, iopt, vals)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n), xmsg
!   LOGICAL, INTENT(IN   ) :: iopt
!   REAL,    INTENT(  OUT) :: vals(5)
!
! Routine to estimate the location, shape, scale and other parameters
! for the Gamma distribution using maximum-likelihood estimation (MLE).
!
! Variables:
!
! n      - size of array x
!
! x      - 1-d data array
!
! xmsg   - missing value of x
!
! iopt   - currently not used. set to zero.
!
! vals   - the maximum-likelihood estimates (MLEs) of the parameters of
!          the Gamma distribution. The parameters are:
!
!            vals(1) - center (location)
!            vals(2) - scale
!            vals(3) - shape
!            vals(4) - variance
!            vals(5) - gamma quantile (median)
!
! It is important to note that the 'center' (aka: location, shift)
! parameter is not the mean. However, it does represent the
! ‘center’ of the distribution. The 'scale' (aka, sigma, beta)
! parameter is not the standard deviation. However, it does govern
! the spread (size) of the deviations about the 'center'.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_extval_gev(n, x, shape, scale, center, iopt, pdf, cdf)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n)
!   REAL,    INTENT(IN   ) :: shape, scale, center
!   INTEGER, INTENT(IN   ) :: iopt
!   REAL,    INTENT(  OUT) :: pdf(n), cdf(n)
!
! Routine to calculate the probability (PDF) and cumulative (CDF)
! distribution functions of the Generalized Extreme Value (GEV)
! distribution given the shape, scale and center parameters.
!
! Variables:
!
! n      - size of array x
!
! x      - 1-d data array
!
! shape  - the shape parameter
!
! scale  - the scale parameter
!
! center - the center (aka, location) parameter
!
! iopt   - currently not used. set to zero.
!
! pdf    - the probability (PDF) distribution function
!
! cdf    - the cumulative (CDF) distribution function
!
! It is important to note that the 'center' (aka: location, shift)
! parameter is not the mean. However, it does represent the
! ‘center’ of the distribution. The 'scale' (aka, sigma, beta)
! parameter is not the standard deviation. However, it does govern
! the spread (size) of the deviations about the 'center'.
!
!---------
!
! Notes:
!
! Value of "-9999.0" of returned pdf/cdf arrays are missing values
!
! The generalized extreme value (GEV) distribution is a family of
! continuous probability distributions developed within extreme
! value theory to combine the Gumbel, Frechet and Weibull families
! also known as type I, II and III extreme value distributions.
!
! The shape parameter "shape" governs the distribution type :
! ... Type I   with shape = 0 ( Gumbel,light tailed)
! ... Type II  with shape > 0 ( Frechet, heavy tailed)
! ... Type III with shape < 0 ( Weibull, bounded)
!
! The GEV distribution is often used as an approximation to model
! the maxima of long (finite) sequences of random variables.
!
! Generalized extreme value distribution:
! https://en.wikipedia.org/wiki/Generalized_extreme_value_distribution
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_extval_gumbel(n, x, scale, center, iopt, pdf, cdf)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n)
!   REAL,    INTENT(IN   ) :: scale, center
!   INTEGER, INTENT(IN   ) :: iopt
!   REAL,    INTENT(  OUT) :: pdf(n), cdf(n)
!
! Routine to calculate the probability (PDF) and cumulative (CDF)
! distribution functions of the Gumbel (Type I) distribution function
! given the scale and center parameters.
!
! Variables:
!
! n      - size of array x
!
! x      - 1-d data array
!
! scale  - the scale parameter
!
! center - the center (aka, location) parameter
!
! iopt   - minmax soecifier.
!          <=0, results in MINIMA (smallest extreme value)
!          > 0, results in MAXIMA (largest extreme value)
!
! pdf    - the probability (PDF) distribution function
!
! cdf    - the cumulative (CDF) distribution function
!
! It is important to note that the 'center' (aka: location, shift)
! parameter is not the mean. However, it does represent the
! ‘center’ of the distribution. The 'scale' (aka, sigma, beta)
! parameter is not the standard deviation. However, it does govern
! the spread (size) of the deviations about the 'center'.
!
!---------
!
! Notes:
!
! Extreme Value Type I distribution ==> Gumbel Distribution
! The shape of the Gumbel model does not depend on the distribution parameters
! It is unbounded on the x-axis
!
! The Gumbel distribution is used to model the distribution of the maximum (or minimum)
! of a number of samples of various distributions.
! The shape of the Gumbel model does not depend on the distribution parameters
! It is bounded on the left and has a heavy upper tail.
!
! See: http://www.itl.nist.gov/div898/handbook/eda/section3/eda366g.htm
!
! minmax <=0 results in MINIMA (smallest extreme value)
! minmax > 0 results in MAXIMA (largest extreme value)
!
! GEV Type I with shape=0
! Domain of attraction for many common distributions ( e.g., normal , exponential,
! gamma), not frequently found to fit ‘real world data ;
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_extval_frechet(n, x, shape, scale, center, iopt, pdf, cdf)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n)
!   REAL,    INTENT(IN   ) :: shape, scale, center
!   INTEGER, INTENT(IN   ) :: iopt
!   REAL,    INTENT(  OUT) :: pdf(n), cdf(n)
!
! Routine to calculate the probability (PDF) and cumulative (CDF)
! distribution functions of the Frechet Type II distribution
! given the shape, scale and location parameters.
!
! Variables:
!
! n      - size of array x
!
! x      - 1-d data array
!
! shape  - the shape parameter
!
! scale  - the scale parameter
!
! center - the center (aka, location) parameter
!
! iopt   - currently not used. set to zero.
!
! pdf    - the probability (PDF) distribution function
!
! cdf    - the cumulative (CDF) distribution function
!
! It is important to note that the 'center' (aka: location, shift)
! parameter is not the mean. However, it does represent the
! ‘center’ of the distribution. The 'scale' (aka, sigma, beta)
! parameter is not the standard deviation. However, it does govern
! the spread (size) of the deviations about the 'center'.
!
!---------
!
! Notes:
!
! Value of "-9999.0" of returned pdf/cdf arrays are missing values
!
! Routine to calculate the probability (PDF) and cumulative (CDF)
! distribution functions of the Frechet Type II distribution given
! the shape, scale and center parameters.
!
! Extreme Value Type II distribution ==> Frechet Distribution
! The Fréchet model relates to MAXIMA (largest extreme value)
!
! http://www.mathwave.com/help/easyfit/html/analyses/distributions/frechet.html
!
! GEV type II with ξ > 0  ( Frechet, heavy tailed)
! Fits found for precipitation, stream flow, economic damage, ..
!
! The Frechet distribution requires lower bound.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_extval_pareto(n, x, shape, scale, location, itype, iopt, pdf, cdf)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n)
!   REAL,    INTENT(IN   ) :: shape, scale, location
!   INTEGER, INTENT(IN   ) :: itype, iopt
!   REAL,    INTENT(  OUT) :: pdf(n), cdf(n)
!
! Routine to calculate the probability (PDF) and cumulative (CDF)
! distribution functions of the Pareto distributions (Generalized,
! Type I, TYpe II) given the shape, scale and location parameters.
!
! Variables:
!
! n      - size of array x
!
! x      - 1-d data array
!
! shape  - the shape parameter
!
! scale  - the scale parameter
!
! center - the center (aka, location) parameter
!
! itype  - distribution specifier
!
!          = 0, means the Generalized Pareto
!          = 1, means the Pareto Type I
!          = 2, means the Pareto Type II
!
! iopt   - currently not used. set to zero.
!
! pdf    - the probability (PDF) distribution function
!
! cdf    - the cumulative (CDF) distribution function
!
! It is important to note that the 'center' (aka: location, shift)
! parameter is not the mean. However, it does represent the
! ‘center’ of the distribution. The 'scale' (aka, sigma, beta)
! parameter is not the standard deviation. However, it does govern
! the spread (size) of the deviations about the 'center'.
!
!---------
!
! Notes:
!
! Value of "-9999.0" of returned pdf/cdf arrays are missing values
!
! Routine to calculate the probability (PDF) and cumulative (CDF)
! distribution functions of the Pareto distributions (Generalized,
! Type I, TYpe II) given the shape, scale and location parameters.
!
! Pareto Distributions:
!   http://www.mathwave.com/help/easyfit/html/analyses/distributions/gen_pareto.html
!   http://www.mathwave.com/help/easyfit/html/analyses/distributions/pareto.html
!   http://www.mathwave.com/help/easyfit/html/analyses/distributions/pareto2.html
!
!   https://en.wikipedia.org/wiki/Pareto_distribution
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_extval_weibull(n, x, shape, scale, center, iopt, pdf, cdf)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n)
!   REAL,    INTENT(IN   ) :: shape, scale, center
!   INTEGER, INTENT(IN   ) :: iopt
!   REAL,    INTENT(  OUT) :: pdf(n), cdf(n)
!
! Routine to calculate the probability (PDF) and cumulative (CDF)
! distribution functions of the Weibull Type III distribution
! given the shape, scale and location parameters.
!
! Variables:
!
! n      - size of array x
!
! x      - 1-d data array
!
! shape  - the shape parameter
!
! scale  - the scale parameter
!
! center - the center (aka, location) parameter
!
! iopt   - currently not used. set to zero.
!
! pdf    - the probability (PDF) distribution function
!
! cdf    - the cumulative (CDF) distribution function
!
! It is important to note that the 'center' (aka: location, shift)
! parameter is not the mean. However, it does represent the
! ‘center’ of the distribution. The 'scale' (aka, sigma, beta)
! parameter is not the standard deviation. However, it does govern
! the spread (size) of the deviations about the 'center'.
!
!---------
!
! Notes:
!
! Routine to calculate the probability (PDF) and cumulative (CDF)
! distribution functions of the Weibull Type III distribution given
! the shape, scale and center parameters.
!
! Extreme Value Type III distribution ==> Weibull Distribution
! The distribution is defined for x>center
! The Weibull model relates to minima (smallest extreme value)
!
! http://www.mathwave.com/help/easyfit/html/analyses/distributions/weibull.html
!
! GEV type III with ξ < 0 ( Weibull, bounded) Fits
! Fits found for temperature, wind speed, pollutants, sea level
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_extval_recurrence_table(n, time, x, dims, iopt, table)
!
!   INTEGER, INTENT(IN   ) :: n
!   INTEGER, INTENT(IN   ) :: time(n)
!   REAL,    INTENT(IN   ) :: x(n)
!   INTEGER, INTENT(IN   ) :: dims
!   LOGICAL, INTENT(IN   ) :: iopt
!   REAL,    INTENT(  OUT) :: table(7,n)
!
! Routine to calculate the recurrence interval (return period),
! cumulative and exceedence probabilities based upon a time series.
!
! Variables:
!
! n      - size of time and x arrays
!
! time   - a array containing 'time' steps. Actually any unique
!          numbering can be used. For example,
!
!          time = (/1901, 19022, 1903, ..., 1901+n-1/)
!
! x      - a array containing observations corresponding to each
!          'time' step.
!
! dims   - currently not used. Set to zero.
!
! iopt   - optional attributes specifier.
!
!          = .FALSE., the returned table is in the order input to
!            the function
!          = .TRUE.,  the returned table will be in order by rank
!
! table  - a seven (7) ranked table entries:
!
!          table(1,:) - the 'time' entry
!          table(2,:) - the 'x' value associated with the 'time'
!          table(3,:) - the Cumulative Probability Rank
!          table(4,:) - the Cumulative Probability
!          table(5,:) - the Exceedance Probability Rank
!          table(6,:) - the Exceedance Probability
!          table(7,:) - the Recurrence Interval
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_extval_return_period(Tr, Pr, Nr)
!
!   REAL, INTENT(IN   ) :: Tr, Pr
!   REAL, INTENT(  OUT) :: Nr
!
! Routine to calculate the period of an event (eg, flood, heat wave,
! drought) occurring given an average event recurrence interval and
! specified probability level.
!
! Variables:
!
! Tr     - the average event recurrence interval.
!
! Pr     - the probability (0<Pr<=1).
!
! Nr     - the return period (recurrence interval)
!
!          Nr = LOG(Pr)/LOG(1-(1.0/Tr))
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_extval_return_prob(Tr, Nr, Pr)
!
!   REAL, INTENT(IN   ) :: Tr, Nr
!   REAL, INTENT(  OUT) :: Pr
!
! Routine to calculate the probability of an event (eg, flood,
! heat wave, drought) given an average event interval and a
! specified exceedance period.
!
! Variables:
!
! Tr     - the average time between events (aka: return period,
!          recurrence interval).
!
! Nr     - the exceedance period (aka: exceedance interval).
!
! Pr     - the eveny probability [0-1] at a specified exceedance
!          interval (aka: return period)
!
!          Pr = 1.0 - (1.0-(1.0/Tr))**Nr
!
!=====================================================================
! Math and Statistics - Bootstrap
!=====================================================================
!
! SUBROUTINE ng_bootstrap_correl(n, x, y, nBoot, Boot, BootAvg, BootStd,&
!                                opt_sample_size, opt_rseeds, opt_rclock,&
!                                opt_sequential)
! SUBROUTINE ng_bootstrap_diff(nx, ny, x, y, nBoot, Boot, BootAvg, BootStd,&
!                              opt_sample_size_x, opt_sample_size_y,&
!                              opt_rseeds, opt_rclock, opt_sequential)
! SUBROUTINE ng_bootstrap_estimate(nBoot, xBoot, fpc, opt, val)
! SUBROUTINE ng_bootstrap_regcoef(n, x, y, nBoot, Boot, BootAvg, BootStd,&
!                                 opt_sample_size, opt_rseeds, opt_rclock,&
!                                 opt_sequential)
! SUBROUTINE ng_bootstrap_stat(n, x, istat, nBoot, Boot, BootAvg, BootStd,&
!                              opt_sample_size, opt_sample_method,&
!                              opt_rseeds, opt_rclock, opt_sequential)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_bootstrap_correl(n, x, y, nBoot, Boot, BootAvg, BootStd,&
!                                opt_sample_size, opt_rseeds, opt_rclock,&
!                                opt_sequential)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n), y(n)
!   INTEGER, INTENT(IN   ) :: nBoot
!   REAL,    INTENT(  OUT) :: Boot(nBoot), BootAvg, BootStd
!
!   INTEGER, INTENT(IN   ), OPTIONAL :: opt_sample_size
!   INTEGER, INTENT(IN   ), OPTIONAL :: opt_rseeds(2), opt_rclock
!   LOGICAL, INTENT(IN   ), OPTIONAL :: opt_sequential
!
! Routine to bootstrap estimates of sample "cross correlations" (ie,
! Pearson's correlation coefficient) between two variables.
!
! Variables:
!
!   n       - Size of sample arrays x and y.
!
!   x, y    - Input vectors with which the calculations are to take place.
!
!   nBoot   - Number of bootstrap data samples to be generated.
!
!   Boot    - Bootstrapped samples (cross correlation), in ascending order
!
!   BootAvg - Average of bootstrapped samples
!
!   BootStd - Standard deviation of bootstrapped samples
!
! Optional arguments:
!
!   opt_sample_size - The size of the sampled array to be used for
!                     the bootstrapped statistics. (positive and <=n)
!                     Default is "n", if argument not present.
!
!   opt_rseeds      - Use its two elements to set the two random seeds.
!                     (See: ng_random_setallseed routine)
!
!   opt_rclock      - Use the 'date' clock to set the two random seeds.
!                     (no concern to the value of this option)
!
!   opt_sequential  - Bootstrapped sub-sample are sequential blocks.
!                     Each 'start index' is random with replacement
!                     BUT then n sequential values.
!
!   Note: (1) Arguments "opt_rseeds" and "opt_rclock" cannot co-present.
!         (2) Use default seeds, if both "opt_rseeds" and "opt_rclock"
!             are not prsent.
!         (3) No explicit 'opt_sequential' option is offered in NCL.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_bootstrap_diff(nx, ny, x, y, nBoot, Boot, BootAvg, BootStd,&
!                              opt_sample_size_x, opt_sample_size_y,&
!                              opt_rseeds, opt_rclock, opt_sequential)
!
!   INTEGER, INTENT(IN   ) :: nx, ny
!   REAL,    INTENT(IN   ) :: x(nx), y(ny)
!   INTEGER, INTENT(IN   ) :: nBoot
!   REAL,    INTENT(  OUT) :: Boot(nBoot), BootAvg, BootStd
!
!   INTEGER, INTENT(IN   ), OPTIONAL :: opt_sample_size_x, opt_sample_size_y
!   INTEGER, INTENT(IN   ), OPTIONAL :: opt_rseeds(2), opt_rclock
!   LOGICAL, INTENT(IN   ), OPTIONAL :: opt_sequential
!
! Routine to bootstrap "mean differences" from two samples.
!
! Variables:
!
!   nx, ny  - Size of sample arrays x and y.
!
!   x, y    - Input vectors with which the calculations are to take place.
!
!   nBoot   - Number of bootstrap data samples to be generated.
!
!   Boot    - Bootstrapped samples (cross correlation), in ascending order
!
!   BootAvg - Average of bootstrapped samples
!
!   BootStd - Standard deviation of bootstrapped samples
!
! Optional arguments:
!
!   opt_sample_size_x - The size of the sampled array to be used for
!   opt_sample_size_y   the bootstrapped statistics. (positive and <=nx[ny])
!                       Default is "nx[ny]", if argument not present.
!
!   opt_rseeds        - Use its two elements to set the two random seeds.
!                       (See: ng_random_setallseed routine)
!
!   opt_rclock        - Use the 'date' clock to set the two random seeds.
!                       (no concern to the value of this option)
!
!   opt_sequential    - Bootstrapped sub-sample are sequential blocks.
!                       Each 'start index' is random with replacement
!                       BUT then n sequential values.
!
!   Note: (1) Arguments "opt_rseeds" and "opt_rclock" cannot co-present.
!         (2) Use default seeds, if both "opt_rseeds" and "opt_rclock"
!             are not prsent.
!         (3) No explicit 'opt_sequential' option is offered in NCL.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_bootstrap_estimate(nBoot, Boot, fpc, val, opt)
!
!   INTEGER, INTENT(IN   ) :: nBoot
!   REAL,    INTENT(IN   ) :: Boot(nBoot)
!   REAL,    INTENT(IN   ) :: fpc
!   REAL,    INTENT(  OUT) :: estimate
!
! Routine to extract the user specified element from the bootstrapped
! values.
!
! Variables:
!
! nBoot - Size of array Boot
!
! Boot  - An array containing the bootstrapped values in ascending
!         order as returned by the ng_bootstrap_* routines.
!
! fpc   - A scalar between 0 and 1 (0.0 <= fpc <= 1.0) which
!         specifies the desired level.
!
! opt   - Currently not used. Set to ,FALSE..
!
! val   - element extracted from the xBoot array.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_bootstrap_regcoef(n, x, y, nBoot, Boot, BootAvg, BootStd,&
!                                 opt_sample_size, opt_rseeds, opt_rclock,&
!                                 opt_sequential)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n), y(n)
!   INTEGER, INTENT(IN   ) :: nBoot
!   REAL,    INTENT(  OUT) :: Boot(nBoot), BootAvg, BootStd
!
!   INTEGER, INTENT(IN   ), OPTIONAL :: opt_sample_size
!   INTEGER, INTENT(IN   ), OPTIONAL :: opt_rseeds(2), opt_rclock
!   LOGICAL, INTENT(IN   ), OPTIONAL :: opt_sequential
!
! Routine to bootstrap estimates of "linear regression coefficient".
!
! Variables:
!
!   n       - Size of sample arrays x and y.
!
!   x, y    - Input vectors with which the calculations are to take place.
!
!   nBoot   - Number of bootstrap data samples to be generated.
!
!   Boot    - Bootstrapped samples (cross correlation), in ascending order
!
!   BootAvg - Average of bootstrapped samples
!
!   BootStd - Standard deviation of bootstrapped samples
!
! Optional arguments:
!
!   opt_sample_size - The size of the sampled array to be used for
!                     the bootstrapped statistics. (positive and <=n)
!                     Default is "n", if argument not present.
!
!   opt_rseeds      - Use its two elements to set the two random seeds.
!                     (See: ng_random_setallseed routine)
!
!   opt_rclock      - Use the 'date' clock to set the two random seeds.
!                     (no concern to the value of this option)
!
!   opt_sequential  - Bootstrapped sub-sample are sequential blocks.
!                     Each 'start index' is random with replacement
!                     BUT then n sequential values.
!
!   Note: (1) Arguments "opt_rseeds" and "opt_rclock" cannot co-present.
!         (2) Use default seeds, if both "opt_rseeds" and "opt_rclock"
!             are not prsent.
!         (3) No explicit 'opt_sequential' option is offered in NCL.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_bootstrap_stat(n, x, istat, nBoot, Boot, BootAvg, BootStd,&
!                              opt_sample_size, opt_sample_method,&
!                              opt_rseeds, opt_rclock, opt_sequential)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n)
!   INTEGER, INTENT(IN   ) :: istat
!   INTEGER, INTENT(IN   ) :: nBoot
!   REAL,    INTENT(  OUT) :: Boot(nBoot), BootAvg, BootStd
!
!   INTEGER, INTENT(IN   ), OPTIONAL :: opt_sample_size
!   INTEGER, INTENT(IN   ), OPTIONAL :: opt_sample_method
!   INTEGER, INTENT(IN   ), OPTIONAL :: opt_rseeds(2), opt_rclock
!   LOGICAL, INTENT(IN   ), OPTIONAL :: opt_sequential
!
! Routine to bootstrap estimates of a "user specified statistic"
! derived from a variable.
!
! Variables:
!
!   n       - Size of sample array x.
!
!   x       - Input vector with which the calculations are to take place.
!
!   istat   - Index to specify the statistic to be bootstrapped.
!             = 0, for the 'mean' ('average')
!             = 1, for the 'standard deviation'
!             = 2, for the 'variance'
!             = 3, for the 'median'
!             = 4, for the 'min'
!             = 5, for the 'max'
!             = 6, for the 'sum'
!
!   nBoot   - Number of bootstrap data samples to be generated.
!
!   Boot    - Bootstrapped samples (cross correlation), in ascending order
!
!   BootAvg - Average of bootstrapped samples
!
!   BootStd - Standard deviation of bootstrapped samples
!
! Optional arguments:
!
!   opt_sample_size   - The size of the sampled array to be used for
!                       the bootstrapped statistics. (positive and <=n)
!                       Default is "n", if argument not present.
!
!   opt_sample_method - Index to specify the sampling method to use
!                       = 1, specify sampling-with-replacement.
!                         This is the default.
!                       = 0, specify sampling-without-replacement.
!
!   opt_rseeds        - Use its two elements to set the two random seeds.
!                       (See: ng_random_setallseed routine)
!
!   opt_rclock        - Use the 'date' clock to set the two random seeds.
!                       (no concern to the value of this option)
!
!   opt_sequential    - Bootstrapped sub-sample are sequential blocks.
!                       Each 'start index' is random with replacement
!                       BUT then n sequential values.
!
!   Note: (1) Arguments "opt_rseeds" and "opt_rclock" cannot co-present.
!         (2) Use default seeds, if both "opt_rseeds" and "opt_rclock"
!             are not prsent.
!         (3) No explicit 'opt_sequential' option is offered in NCL.
!
!=====================================================================
! Earth Science - Climatology
!=====================================================================
!
! SUBROUTINE ng_clmMon     (ntim, x, xmsg, clm)       ! monthly means (climatology)
! SUBROUTINE ng_stdMon     (ntim, x, xmsg, std)       ! monthly standard deviations
! SUBROUTINE ng_calcMonAnom(ntim, x, xmsg, clm, anom) ! monthly anomalies
!
! SUBROUTINE ng_clmDay     (ntim, yyyyddd, x, xmsg, clm)       ! daily means (climatology)
! SUBROUTINE ng_smthClmDay (clm, xmsg, nHarm, clmsm)           ! smooth daily means
! SUBROUTINE ng_calcDayAnom(ntim, yyyyddd, x, xmsg, clm, anom) ! daily anomalies
!
! SUBROUTINE ng_month_to_annual  (nloc, nyrs, xmon, xspv, iopt, xann) ! turn monthly values to annual values
! SUBROUTINE ng_month_to_season  (npts, ntim, xmon, csea, xsea)
! SUBROUTINE ng_month_to_season12(npts, ntim, xmon, xsea)
! SUBROUTINE ng_month_to_seasonN (npts, ntim, xmon, nsea, csea, xsea)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_clmMon(ntim, x, xmsg, clm)
!
!   INTEGER, INTENT(IN   ) :: ntim
!   REAL,    INTENT(IN   ) :: x(ntim)
!   REAL,    INTENT(IN   ) :: xmsg    ! missing value
!   REAL,    INTENT(  OUT) :: clm(12) ! monthly means
!
! Routine to calculate long term monthly means (monthly climatology)
! from monthly data
!
! The time dimension "ntim" must be a multiple of 12
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_stdMon(ntim, x, xmsg, std)
!
!   INTEGER, INTENT(IN   ) :: ntim
!   REAL,    INTENT(IN   ) :: x(ntim)
!   REAL,    INTENT(IN   ) :: xmsg    ! missing value
!   REAL,    INTENT(  OUT) :: std(12) ! monthly standard deviations
!
! Routine to calculate standard deviations of long term monthly means
! from monthly data
!
! The time dimension "ntim" must be a multiple of 12
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_calcMonAnom(ntim, x, xmsg, clm, anom)
!
!   INTEGER, INTENT(IN   ) :: ntim
!   REAL,    INTENT(IN   ) :: x(ntim)
!   REAL,    INTENT(IN   ) :: xmsg       ! missing value
!   REAL,    INTENT(IN   ) :: clm(12)    ! monthly means
!   REAL,    INTENT(  OUT) :: anom(ntim) ! monthly anomalies
!
! Routine to calculat monthly anomalies by subtracting the long term mean
!
! The time dimension "ntim" must be a multiple of 12
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_clmDay(ntim, yyyyddd, x, xmsg, clm)
!
!   INTEGER, INTENT(IN   ) :: ntim
!   INTEGER, INTENT(IN   ) :: yyyyddd(ntim)
!   REAL,    INTENT(IN   ) :: x(ntim)
!   REAL,    INTENT(IN   ) :: xmsg
!   REAL,    INTENT(  OUT) :: clm(366)
!
! Routine to calculate the mean Annual Cycle from daily data.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_smthClmDay(clm, xmsg, nHarm, clmsm)
!
!   REAL,    INTENT(IN   ) :: clm(366)
!   REAL,    INTENT(IN   ) :: xmsg
!   INTEGER, INTENT(IN   ) :: nHarm
!   REAL,    INTENT(  OUT) :: clmsm(366)
!
! Calculate a smooth annual cycle using the output from ng_clmDay.
! A Fourier analysis is performed via an FFT. Next, all harmonics
! greater than nHarm are set to zero and a backward transform is
! performed.
!
! Note: *** No missing values allowed ***
!
! The number of harmonics that will be used to construct the smoothed
! mean annual cycle. Usually, nHarm is 1 to 3 with 2 being most common.
! A value of 2 means to use the annual and semi-annual harmonics only.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_calcDayAnom(ntim, yyyyddd, x, xmsg, clm, anom)
!
!   INTEGER, INTENT(IN   ) :: ntim
!   INTEGER, INTENT(IN   ) :: yyyyddd(ntim)
!   REAL,    INTENT(IN   ) :: x(ntim)
!   REAL,    INTENT(IN   ) :: xmsg
!   REAL,    INTENT(IN   ) :: clm(366)
!   REAL,    INTENT(  OUT) :: anom(ntim)
!
! Routine to calculate daily anomalies from a daily data climatology.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_month_to_annual(nloc, nyrs, xmon, xspv, iopt, xann)
!
!   INTEGER, INTENT(IN   ) :: nloc, nyrs
!   REAL,    INTENT(IN   ) :: xmon(nloc,nyrs*12)
!   REAL,    INTENT(IN   ) :: xspv
!   INTEGER, INTENT(IN   ) :: iopt
!   REAL,    INTENT(  OUT) :: xann(nloc,nyrs)
!
! Routine to turn monthly values (xmon) to annual values (xann)
!
! Variables:
!
!   nloc - First dimension of arrays xmon and xann
!
!   nyrs - Second dimension of arrays xmon and xann, the "time" dimension
!
!   xmon - An array containing monthly values. The "time" dimension
!          must be the rightgmost (i.e., second) dimension. Ideally,
!          the size of the "time" dimension is evenly divisible by 12.
!
!   xspv - the missing value of array xmon
!
!   iopt - =0, compute the annual "sum" of 12 months.
!              (return "xspv", if any month is missing)
!
!          =[1,12], compute annual "mean" for iopt or more non-missing months
!              (return "xspv", if COUNT(non-missing-months) < iopt )
!
!   xann - returned annual "sum" (iopt=0) or "mean" (iopt>=1) values
!
!-------------------
!
! Typical usage is that an array of monthly precipitation totals (e.g., mm)
! or monthly mean temperatures are input. For precipitation, generally opt=0,
! and the sum of the 12 values is returned. For temperature, generally opt=1,
! and the (unweighted) annual average is returned.
!
! Usage:
!
!   INTEGER, PARAMETER :: nloc=..., nlon=..., nlat=..., nlev=...
!   INTEGER, PARAMETER :: nyrs=20, nmon=nyrs*12
!
!   REAL :: D1_mon(nmon), D2_mon(nloc,nmon), D3_mon(nlon,nlat,ntim), D4_mon(nlon,nlat,nlev,ntim)
!   REAL :: D1_ann(nyrs), D2_ann(nloc,nyrs), D3_ann(nlon,nlat,nyrs), D4_ann(nlon,nlat,nlev,nyrs)
!
!   CALL ng_month_to_annual(1             , nyrs, d1_mon, xspv, iopt, xd1_ann)
!
!   CALL ng_month_to_annual(nloc          , nyrs, d1_mon, xspv, iopt, xd1_ann)
!
!   CALL ng_month_to_annual(nlon*nlat     , nyrs, d1_mon, xspv, iopt, xd1_ann)
!
!   CALL ng_month_to_annual(nlon*nlat*nlev, nyrs, d1_mon, xspv, iopt, xd1_ann)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_month_to_season(npts, ntim, xmon, csea, xsea)
!
!   INTEGER,      INTENT(IN   ) :: npts, ntim
!   REAL,         INTENT(IN   ) :: xmon(npts,ntim)
!   CHARACTER(3), INTENT(IN   ) :: csea
!   REAL,         INTENT(  OUT) :: xsea(npts,ntim/12)
!
! Routine to compute a user-specified three-month seasonal mean
! (DJF, JFM, FMA, MAM, AMJ, MJJ, JJA, JAS, ASO, SON, OND, NDJ).
! The first average (DJF=JF) and the last average (NDJ=ND) are
! actually two-month averages.
!
! The input "xmon" are assumed to contain monthly mean data
! The size of "nime" MUST be divisible by 12.
! Also, it is assumed the "Jan" is the 1st month.
!
! Variables:
!
!   npts - fist (non-time) dimension of array xmon
!
!   ntim - second (time) dimension of array xmon
!
!   xmon - 2d array contains monthly mean data
!
!   csea - a 3-characters string representing the season to calculate
!          can only be one of following 12 values
!
!          "DJF", "JFM", "FMA", "MAM", "AMJ", "MJJ"
!          "JJA", "JAS", "ASO", "SON", "OND", "NDJ"
!
!   xsea - computed three-month seasonal mean
!
!---------
!
! Special cases, for xmon is not a 2d array
!
!   INTEGER, PARAMETER :: nyrs=..., nmon=nyrs*12, ...
!
!   REAL :: x1mon(nmon), x4mon(nlon,nlat,nlev,nmon)
!   REAL :: x1sea(nyrs), x4sea(nlon,nlat,nlev,nyrs)
!
!   CALL ng_month_to_season(             1, nmon, x1mon, csea, x1sea)
!   CALL ng_month_to_season(nlon*nlat*nlev, nmon, x4mon, csea, x4sea)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_month_to_season12(npts, ntim, xmon, xsea)
!
!   INTEGER,      INTENT(IN   ) :: npts, ntim
!   REAL,         INTENT(IN   ) :: xmon(npts,ntim)
!   REAL,         INTENT(  OUT) :: xsea(npts,ntim)
!
! Routine to compute three-month seasonal means (DJF, JFM, FMA,
! MAM, AMJ, MJJ, JJA, JAS, ASO, SON, OND, NDJ). The first seasonal
! average (DJF=JF) and the last seasonal average (NDJ=ND) are
! actually two-month averages.
!
! Variables:
!
!   npts - fist (non-time) dimension of array xmon
!
!   ntim - second (time) dimension of array xmon
!          must be divisible by 12
!
!   xmon - 2d array contain monthly mean data and the first record
!          is assumed to be January.
!
!   xsea - computed three-month seasonal means
!
!---------
!
! Special cases, for xmon is not a 2d array
!
!   INTEGER, PARAMETER :: nyrs=..., nmon=nyrs*12, ...
!
!   REAL :: x1mon(nmon), x4mon(nlon,nlat,nlev,nmon)
!   REAL :: x1sea(nmon), x4sea(nlon,nlat,nlev,nmon)
!
!   CALL ng_month_to_season12(             1, nmon, x1mon, x1sea)
!   CALL ng_month_to_season12(nlon*nlat*nlev, nmon, x4mon, x4sea)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_month_to_seasonN(npts, ntim, xmon, nsea, csea, xsea)
!
!   INTEGER,      INTENT(IN   ) :: npts, ntim
!   REAL,         INTENT(IN   ) :: xmon(npts,ntim)
!   INTEGER,      INTENT(IN   ) :: nsea
!   CHARACTER(3), INTENT(IN   ) :: csea(nsea)
!   REAL,         INTENT(  OUT) :: xsea(npts,ntim/12,nsea)
!
! Routine to compute a user-specified list three-month seasonal means
! (DJF, JFM, FMA, MAM, AMJ, MJJ, JJA, JAS, ASO, SON, OND, NDJ).
! The first average (DJF=JF) and the last average (NDJ=ND) are actually
! two-month averages.
!
! The input "xmon" are assumed to contain monthly mean data
! The size of "nime" MUST be divisible by 12.
! Also, it is assumed the "Jan" is the 1st month.
!
! Variables:
!
!   npts - fist (non-time) dimension of array xmon
!
!   ntim - second (time) dimension of array xmon
!
!   xmon - 2d array contain monthly mean data
!
!   nsea - dimension of array season
!
!   csea - array of strings representing the seasons to calculate.
!          all elements are 3-characters string representing the
!          season to calculate and can only be one of following
!          12 values
!
!          "DJF", "JFM", "FMA", "MAM", "AMJ", "MJJ"
!          "JJA", "JAS", "ASO", "SON", "OND", "NDJ"
!
!   xsea - computed three-month seasonal means
!
!=====================================================================
! Earth Science - CESM
!=====================================================================
!
! SUBROUTINE ng_pres_hybrid_ccm (mlon, nlat, psfc, pmsg, p0, klev, hya, hyb, phy)
! SUBROUTINE ng_dpres_hybrid_ccm(mlon, nlat, psfc, pmsg, p0, klev, hya, hyb, dphy)
!
! SUBROUTINE ng_vinth2p      (nlon, nlat, nlevi, dati, psfc, spvl, p0,            &
!                             hbcofa, hbcofb, intyp, kxtrp,         nlevo, plevo, dato)
! SUBROUTINE ng_vinth2p_ecmwf(nlon, nlat, nlevi, dati, psfc, spvl, p0, tbot, phis,&
!                             hbcofa, hbcofb, intyp, kxtrp, varflg, nlevo, plevo, dato)
!
! SUBROUTINE ng_band_pass_area_time  (nlon, nlat, ntim, x, xmsg, spd, bpf,&
!                                     wy, xts, opt_detrend, opt_Nrun)
! SUBROUTINE ng_band_pass_hovmueller (nlon, nlat, ntim, x, xmsg, spd, bpf,&
!                                     wy, xts, opt_detrend)
! SUBROUTINE ng_band_pass_latlon_time(nlon, nlat, ntim, x, xmsg, spd, bpf,&
!                                     xts, opt_detrend, opt_fft, opt_taper)
!
! SUBROUTINE ng_mjo_xcor_lag_season(ntim, npts, ref, x, xmsg, mxlag, ccr,&
!                                   opt_smth9)
! SUBROUTINE ng_mjo_xcor_lag(ntim, npts, date, ref, x, xmsg, seaName,&
!                            mxlag, ccr, opt_smth9)
! SUBROUTINE ng_mjo_wavenum_freq_season(nlon, ntim, x, xmsg, date, seaName, nday,&
!                                       spectra, opt_freq, opt_wave, opt_smth9)
! SUBROUTINE ng_mjo_spectra_season(nlon, nlat, ntim, x, xmsg, wy, date, seaName, nday,&
!                   smjo, smjo_spcx, smjo_frq, smjo_bw, smjo_xvari, smjo_xlag1,&
!                   opt_detrend, opt_detrend_seg, opt_smooth_seg, opt_taper_seg)
! SUBROUTINE ng_mjo_cross(nlon, nlat, ntim, x, y, xmsg, ymsg, segLen,&
!                         segOverLap, stc, stc_freq, stc_wave, stc_dof,&
!                         stc_prob, stc_prob_coh2, stc_segmentLength,&
!                         stc_segmentOverLap, stc_segmentRepeat)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_pres_hybrid_ccm(mlon, nlat, psfc, pmsg, p0, klev, hya, hyb, phy)
!
!   INTEGER, INTENT(IN   ) :: mlon, nlat
!   REAL,    INTENT(IN   ) :: psfc(mlon,nlat), pmsg, p0
!   INTEGER, INTENT(IN   ) :: klev
!   REAL,    INTENT(IN   ) :: hya(klev), hyb(klev)
!   REAL,    INTENT(  OUT) :: phy(mlon,nlat,klev)
!
! Routine to calculate pressure at the hybrid levels.
!
! Variables:
!
!   mlon - longitude dimension
!
!   nlat - latitude  dimension
!
!   psfc - surface pressure data in Pa or hPa (mb)
!
!   pmsg - missing value of psfc
!
!   p0   - surface reference pressure, must have the same units as psfc
!
!   klev - number of levels, size of arrays hya and hyb
!
!   hya  - "a" or pressure hybrid coef
!
!   hyb  - "b" or sigma coeficient
!
!   phy  - calculated pressure at hybrid levels [Pa]
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_dpres_hybrid_ccm(mlon, nlat, psfc, pmsg, p0, klev, hya, hyb, dphy)
!
!   INTEGER, INTENT(IN   ) :: mlon, nlat
!   REAL,    INTENT(IN   ) :: psfc(mlon,nlat), pmsg, p0
!   INTEGER, INTENT(IN   ) :: klev
!   REAL,    INTENT(IN   ) :: hya(klev), hyb(klev)
!   REAL,    INTENT(  OUT) :: dphy(mlon,nlat,klev-1)
!
! Routine to calculate the pressure differences of a hybrid coordinate system
!
! Variables:
!
!   mlon - longitude dimension
!
!   nlat - latitude  dimension
!
!   psfc - surface pressure data in Pa or hPa (mb)
!
!   pmsg - missing value of psfc
!
!   p0   - surface reference pressure, must have the same units as psfc
!
!   klev - number of levels, size of arrays hya and hyb
!
!   hya  - "a" or pressure hybrid coef
!
!   hyb  - "b" or sigma coeficient
!
!   dphy - calculated delta pressure [Pa; always positive]
!
! Note: dphy will have one less vertical level
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_vinth2p(nlon, nlat, nlevi, dati, psfc, spvl, p0, hbcofa, hbcofb,&
!                       intyp, kxtrp, nlevo, plevo, dato)
!   IMPLICIT NONE
!
!   INTEGER, INTENT(IN   ) :: nlon, nlat, nlevi
!   REAL,    INTENT(IN   ) :: dati(nlon,nlat,nlevi)
!   REAL,    INTENT(IN   ) :: psfc(nlon,nlat), spvl, p0
!   REAL,    INTENT(IN   ) :: hbcofa(nlevi), hbcofb(nlevi)
!   INTEGER, INTENT(IN   ) :: intyp
!   LOGICAL, INTENT(IN   ) :: kxtrp
!   INTEGER, INTENT(IN   ) :: nlevo
!   REAL,    INTENT(IN   ) :: plevo(nlevo)
!   REAL,    INTENT(  OUT) :: dato(nlon,nlat,nlevo)
!
! Routine to interpolate CAM (Community Atmosphere Model) hybrid
! coordinates to pressure coordinates.
!
! Variables:
!
!  nlon   - longitude dimension
!  nlat   - latitude  dimension
!  nlevi  - number of levels for the hybrid data
!
!  datai  - input data array (in hybrid coordinates) to be interpolated
!
!  psfc   - surface pressures in Pa
!
!  spvl   - missing value of array psfc
!           special value to use when data is not extrapolated
!
!  p0     - surface reference pressure in Mb.
!
!  hbcofa - hybrid A coefficients, the order must be top-to-bottom
!           (These are expected to be normalized to one (1.0). If not,
!           divide by p0)
!
!  hbcofb - hybrid B coefficients, the order must be top-to-bottom
!           (These are expected to be normalized to one (1.0). If not,
!           divide by p0)
!
!  intyp  - flag to indacate the interpolation type
!           1 - LINEAR,
!           2 - LOG,
!           3 - LOG LOG
!
!  kxtrp  - flag which indicates whether or not extrapolation will be
!           used when the output pressure surface is below the lowest
!           level of the model.
!           .FALSE. - don't extrapolate use special value spvl
!           .TRUE.  - extrapolate data using ecmwf formulation
!                     below psfc
!
!  nlevo  - number of output levels for pressure data
!
!  plevo  - output pressure levels in mb.
!
!  datao  - output data array interpolated to pressure coordinates
!
!---------------------------------------
!
! THIS ROUTINE INTERPLOATES CCM2/3 HYBRID COORDINATE DATA
! TO PRESSURE COORDINATES USING PRESSURE SURFACES AS THE
! COORDINATE SURFACE WHERE THE INTERPOLATION IS DONE.  THE
! TYPE OF INTERPOLATION IS CURRENTLY A VARIANT OF TRANSFORMED
! PRESSURE COORDINATES WITH THE  INTERPOLATION TYPE
! SPECIFIED BY INTYP.  ALL HYBRID COORDINATE VALUES ARE
! TRANSFORMED TO PRESSURE VALUES. WHERE THE
! FORMULA FOR THE PRESSURE OF A HYBRID SURFACE IS;
!      P(K) = HBCOFA(LEVH,K)*P0 + HBCOFB(LEVH,K)*PSFC
! WHERE,
!      HBCOFA - IS THE "A" OR PRESSURE HYBRID COEF
!      LEVH   - IS THE LAYER SURFACE (INTERFACE=1 MIDPOINT=2)
!      P0     - IS THE BASE PRESSURE IN MB
!      K      - THE LEVEL INDEX (RUNNING FROM TOP TO BOTTOM)
!      HBCOFB - IS THE "B" OR SIGMA COEFICIENT
!      P(K)   - IS THE PRESSURE OF A HYBRID SURFACE IN MB.
!      PSFC   - IS THE SURFACE PRESSURE IN PASCALS
!               (MB = .01*PASCALS
!
! FOR HYBRID DATA AT LEVEL INTERFACES SINCE THERE IS ONE
! MORE VERTICAL LEVEL FOR INTERFACES THAN FOR LEVEL MIDPOINTS
! IT IS ASSUNMED THAT THE FIRST INTERFACE LEVEL WITH A DATA
! VALUE IS THE SECOND LEVEL FROM THE TOP.
!
! ON INPUT-
!    DATI    - 3 DIMENSIONAL ARRAY (I,J,K) CONTAINING DATA
!              ON HYBRID SURFACES  WHERE I IS LONGTIUDE, J
!              IS LATITUDE AND K IS THE VERTICAL HYBRID
!              COORDINATE.  THE VERTICAL DATA RUN TOP TO BOTTOM.
!              SIGMA DATA WITH THE DATA ORDERED TOP TO BOTTOM.
!    HBCOFA  - A one-dimensional array containing the hybrid A
!              coefficients.  Must have the same dimension size
!              as the level dimension of datai.   The order must
!              be top-to-bottom. (These are expected to be normalized
!              to one (1.0). If not, divide by P0.)
!    HBCOFB  - SAME AS HCOFA BUT FOR THE "B" OR SIGMA COEFICIENT
!    P0      - BASE PRESSURE IN MB FOR COMPUTING PRESSURE
!              OF A HYBRID COORDINATE LEVEL
!    PLEVO   - LIST OF OUTPUT PRESSURE SURFACES IN MB
!              LOW TO HIGH PRESSURE
!    INTYP   - A FLAG INDICATING INTERPOLATION FOR EACH
!              FIELD (1 - LINEAR,2 - LOG ,3 - LOG LOG)
!              WHERE EACH INTERPOLATION IS DONE IN TRANSFORMED
!              PRESSURE COORDINATES.
!    PSFC    - MODEL SFC PRESSURE IN PASCALS (WILL BE CONVERTED
!              TO MB)
!    NLON    - LONGITUDINAL DIMENSION OF THE DATA.
!    NLAT    - LATITUDINAL DIMENSION OF THE DATA.
!    NLEVI   - NO. OF LEVELS FOR THE HYBRID DATA
!    NLEVO   - NUMBER OF OUTPUT LEVELS FOR PRESSURE DATA
!    KXTRP   - FLAG WHICH INDICATES WHETHER OR NOT
!              EXTRAPOLATION WILL BE USED WHEN THE OUTPUT
!              PRESSURE SURFACE IS BELOW THE LOWEST LEVEL
!              OF THE MODEL.
!                 .FALSE. - DON'T EXTRAPOLATE USE SPECIAL VALUE SPVL
!                 .TRUE.  - EXTRAPOLATE DATA
!    SPVL    - SPECIAL VALUE TO USE WHEN DATA IS NOT
!              EXTRAPOLATED
!
! ON OUTPUT-
!    DATO  - 3 DIMENSIONAL ARRAY TO HOLD DATA INTERPOLATED
!            TO PRESSURE SURFACES.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_vinth2p_ecmwf(nlon, nlat, nlevi, dati, psfc, spvl, p0, tbot, phis,&
                              hbcofa, hbcofb, intyp, kxtrp, varflg, nlevo, plevo, dato)
!
!   INTEGER, INTENT(IN   ) :: nlon, nlat, nlevi
!   REAL,    INTENT(IN   ) :: dati(nlon,nlat,nlevi)
!   REAL,    INTENT(IN   ) :: psfc(nlon,nlat), spvl, p0
!   REAL,    INTENT(IN   ) :: tbot(nlon,nlat), phis(nlon,nlat)
!   REAL,    INTENT(IN   ) :: hbcofa(nlevi), hbcofb(nlevi)
!   INTEGER, INTENT(IN   ) :: intyp
!   LOGICAL, INTENT(IN   ) :: kxtrp
!   INTEGER, INTENT(IN   ) :: varflg
!   INTEGER, INTENT(IN   ) :: nlevo
!   REAL,    INTENT(IN   ) :: plevo(nlevo)
!   REAL,    INTENT(  OUT) :: dato(nlon,nlat,nlevo)
!
! Routine to interpolate CESM hybrid coordinates to pressure coordinates
! but uses an ECMWF formulation to extrapolate values below ground.
!
! Variables:
!
!  nlon   - longitude dimension
!  nlat   - latitude  dimension
!  nlevi  - number of levels for the hybrid data
!
!  datai  - input data array (in hybrid coordinates) to be interpolated
!
!  psfc   - surface pressures in Pa
!
!  spvl   - missing value of array psfc
!           special value to use when data is not extrapolated
!
!  p0     - surface reference pressure in Mb.
!
!  tbot   - temperature at the lowest (i.e, closest to the surface) level
!           used only if varflg=-1 (ie, geopotential height)
!
!  phis   - surface geopotential (m^2/sec^2)
!
!  hbcofa - hybrid A coefficients, the order must be top-to-bottom
!           (These are expected to be normalized to one (1.0). If not,
!           divide by p0)
!
!  hbcofb - hybrid B coefficients, the order must be top-to-bottom
!           (These are expected to be normalized to one (1.0). If not,
!           divide by p0)
!
!  intyp  - flag to indacate the interpolation type
!           1 - LINEAR,
!           2 - LOG,
!           3 - LOG LOG
!
!  kxtrp  - flag which indicates whether or not extrapolation will be
!           used when the output pressure surface is below the lowest
!           level of the model.
!           .FALSE. - don't extrapolate use special value spvl
!           .TRUE.  - extrapolate data using ecmwf formulation
!                     below psfc
!
!  varflg - flag indicating which variable to interpolate:
!            1 = geopotential temperature,
!           -1 = geopotential height,
!            0 = any other variable
!
!  nlevo  - number of output levels for pressure data
!
!  plevo  - output pressure levels in mb.
!
!  datao  - output data array interpolated to pressure coordinates
!
!---------------------------------------
!
! THIS ROUTINE INTERPLOATES CCM2/3 HYBRID COORDINATE DATA
! TO PRESSURE COORDINATES USING PRESSURE SURFACES AS THE
! COORDINATE SURFACE WHERE THE INTERPOLATION IS DONE.  THE
! TYPE OF INTERPOLATION IS CURRENTLY A VARIANT OF TRANSFORMED
! PRESSURE COORDINATES WITH THE  INTERPOLATION TYPE
! SPECIFIED BY INTYP.  ALL HYBRID COORDINATE VALUES ARE
! TRANSFORMED TO PRESSURE VALUES. WHERE THE
! FORMULA FOR THE PRESSURE OF A HYBRID SURFACE IS;
!      P(K) = HBCOFA(LEVH,K)*P0 + HBCOFB(LEVH,K)*PSFC
! WHERE,
!      HBCOFA - IS THE "A" OR PRESSURE HYBRID COEF
!      LEVH   - IS THE LAYER SURFACE (INTERFACE=1 MIDPOINT=2)
!      P0     - IS THE BASE PRESSURE IN MB
!      K      - THE LEVEL INDEX (RUNNING FROM TOP TO BOTTOM)
!      HBCOFB - IS THE "B" OR SIGMA COEFICIENT
!      P(K)   - IS THE PRESSURE OF A HYBRID SURFACE IN MB.
!      PSFC   - IS THE SURFACE PRESSURE IN PASCALS
!               (MB = .01*PASCALS
!
! FOR HYBRID DATA AT LEVEL INTERFACES SINCE THERE IS ONE
! MORE VERTICAL LEVEL FOR INTERFACES THAN FOR LEVEL MIDPOINTS
! IT IS ASSUNMED THAT THE FIRST INTERFACE LEVEL WITH A DATA
! VALUE IS THE SECOND LEVEL FROM THE TOP.
!
! ON INPUT-
!    DATI    - 3 DIMENSIONAL ARRAY (I,J,K) CONTAINING DATA
!              ON HYBRID SURFACES  WHERE I IS LONGTIUDE, J
!              IS LATITUDE AND K IS THE VERTICAL HYBRID
!              COORDINATE.  THE VERTICAL DATA RUN TOP TO BOTTOM.
!              SIGMA DATA WITH THE DATA ORDERED TOP TO BOTTOM.
!    HBCOFA  - A one-dimensional array containing the hybrid A
!              coefficients.  Must have the same dimension size
!              as the level dimension of datai.   The order must
!              be top-to-bottom. (These are expected to be normalized
!              to one (1.0). If not, divide by P0.)
!    HBCOFB  - SAME AS HCOFA BUT FOR THE "B" OR SIGMA COEFICIENT
!    P0      - BASE PRESSURE IN MB FOR COMPUTING PRESSURE
!              OF A HYBRID COORDINATE LEVEL
!    PLEVO   - LIST OF OUTPUT PRESSURE SURFACES IN MB
!              LOW TO HIGH PRESSURE
!    INTYP   - A FLAG INDICATING INTERPOLATION FOR EACH
!              FIELD (1 - LINEAR,2 - LOG ,3 - LOG LOG)
!              WHERE EACH INTERPOLATION IS DONE IN TRANSFORMED
!              PRESSURE COORDINATES.
!    PSFC    - MODEL SFC PRESSURE IN PASCALS (WILL BE CONVERTED
!              TO MB)
!    NLON    - LONGITUDINAL DIMENSION OF THE DATA.
!    NLAT    - LATITUDINAL DIMENSION OF THE DATA.
!    NLEVI   - NO. OF LEVELS FOR THE HYBRID DATA
!    NLEVO   - NUMBER OF OUTPUT LEVELS FOR PRESSURE DATA
!    KXTRP   - FLAG WHICH INDICATES WHETHER OR NOT
!              EXTRAPOLATION WILL BE USED WHEN THE OUTPUT
!              PRESSURE SURFACE IS BELOW THE LOWEST LEVEL
!              OF THE MODEL.
!                 .FALSE. - DON'T EXTRAPOLATE USE SPECIAL VALUE SPVL
!                 .TRUE.  - EXTRAPOLATE DATA using ECMWF formulation
!                           below PSFC
!    SPVL    - SPECIAL VALUE TO USE WHEN DATA IS NOT
!              EXTRAPOLATED
!    varflg  - flag which indicates the name of the variable
!              -1 means geopotential (Z)
!              +1 means geopotential (T)
!               0 any other variable
!    tbot    - temperature at level closest to ground
!    phis    - surface geopotential
!
! ON OUTPUT-
!    DATO  - 3 DIMENSIONAL ARRAY TO HOLD DATA INTERPOLATED
!            TO PRESSURE SURFACES.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_band_pass_area_time(nlon, nlat, ntim, x, xmsg, spd, bpf,&
!                                   wy, xts, opt_detrend, opt_Nrun)
!
!   INTEGER, INTENT(IN   ) :: nlon, nlat, ntim
!   REAL,    INTENT(IN   ) :: x(nlon,nlat,ntim), xmsg
!   INTEGER, INTENT(IN   ) :: spd, bpf(3)
!   REAL,    INTENT(IN   ) :: wy(nlat)
!   REAL,    INTENT(  OUT) :: xts(ntim,3)
!   LOGICAL, INTENT(IN), OPTIONAL :: opt_detrend
!   INTEGER, INTENT(IN), OPTIONAL :: opt_Nrun
!
! Routine to create a time series of area averages; band pass filter
! the resulting area averaged time series and calculate other
! statistics.
!
! Variables:
!
!   nlon  - The longitudinal dimension
!
!   nlat  - The latitudinal dimension
!
!   ntim  - The time dimension
!
!   x     - A three dimensional variable array
!           **missing data not allowed**
!
!   xmsg  - Missing value
!
!   spd   - Sampling rate. For example: if srate refers to "samples per day",
!           then, srate is one of the following [1,2,4,8,12,24]. These correspond
!           to [24,12,6,3,2,1] hour sampling rates. Other common sampling units
!           are "samples per year" and "samples per month".
!
!   bpf   - An integer array of length 3. The first two elements contain the
!           band pass start and end times. The last element is the number of
!           weights to be used.
!
!   wy    - A one-dimensional array containing the latitudinal weights.
!
!   xts   - Three returned time series
!           xts(:,1) - band pass filtered areal averages
!           xts(:,2) - raw areal averages
!           xts(:,3) - running variances
!
!   opt_detrend - Series xts(:,2) will be detrended, if present and .TRUE.
!                 Default: .FALSE.
!
!   opt_Nrun    - The number of values to be used in the running average
!                 of variance. This should be in units of days and it should
!                 be an odd number. Default: 101
!
! Notes:
!
!   At each time step, weighted areal averages are computed using wgt_areaave.
!   The resulting time series is band-pass filtered using Lanczos weights
!   (filwgts_lanczos). The user must be aware that the appropriate number of
!   filter weights is a direct function of the band pass period. The shorter
!   the period, the more weights that will be required to sufficiently resolve
!   the desired period.
!
!   The input array, x, should have sufficient 'temporal padding' so that
!   the filter will have its desired result over the period of interest.
!   For example, if daily mean data, spd=1 (samples per day), are being
!   analyzed and bpf(2)=201, then the input array should have 100 (=bpf(2)/2)
!   days padding before and after the time period of focus.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_band_pass_hovmueller(nlon, nlat, ntim, x, xmsg, spd, bpf,&
!                                    wy, xts, opt_detrend)
!
!   INTEGER, INTENT(IN   ) :: nlon, nlat, ntim
!   REAL,    INTENT(IN   ) :: x(nlon,nlat,ntim), xmsg
!   INTEGER, INTENT(IN   ) :: spd, bpf(3)
!   REAL,    INTENT(IN   ) :: wy(nlat)
!   REAL,    INTENT(  OUT) :: xts(nlon,ntim)
!   LOGICAL, INTENT(IN), OPTIONAL :: opt_detrend
!
! Routine to create a band-pass filtered time series suitable for a
! time vs longitude (Hovmueller) plot.
!
! Variables:
!
!   nlon  - The longitudinal dimension
!
!   nlat  - The latitudinal dimension
!
!   ntim  - The time dimension
!
!   x     - A three dimensional variable array
!           **missing data not allowed**
!
!   xmsg  - Missing value
!
!   spd   - Sampling rate. For example: if srate refers to "samples per day",
!           then, srate is one of the following [1,2,4,8,12,24]. These correspond
!           to [24,12,6,3,2,1] hour sampling rates. Other common sampling units
!           are "samples per year" and "samples per month".
!
!   bpf   - An integer array of length 3. The first two elements contain the
!           band pass start and end times. The last element is the number of
!           weights to be used.
!
!   wy    - A 1d array containing the latitudinal weights.
!
!   xts   - A 2d rray containing areal weighted and band-passed filtered values.
!
!   opt_detrend - Series xts will be detrended in time, if present and .TRUE.
!                 Default: .FALSE.
!
! Notes:
!
!   At each time step, weighted latitudinal averages are computed using
!   dim_avg_wgt. The resulting array is band-pass filtered in time using
!   Lanczos weights (filwgts_lanczos). The user must be aware that the
!   appropriate number of filter weights is a direct function of the band
!   pass period. The shorter the period, the more weights that will be
!   required to sufficiently resolve the desired period.
!
!   The input array, x, should have sufficient 'temporal padding' so that
!   the filter will have its desired result over the period of interest.
!   For example, if daily mean data, spd=1 (samples per day), are being
!   analyzed and bpf(2)=201, then the input array should have 100 (=bpf(2)/2)
!   days padding before and after the time period of focus.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_band_pass_latlon_time(nlon, nlat, ntim, x, xmsg, spd, bpf,&
!                                     xts, opt_detrend, opt_fft, opt_taper)
!
!   INTEGER, INTENT(IN   ) :: nlon, nlat, ntim
!   REAL,    INTENT(IN   ) :: x(nlon,nlat,ntim), xmsg
!   INTEGER, INTENT(IN   ) :: spd, bpf(3)
!   REAL,    INTENT(  OUT) :: xts(nlon,nlat,ntim)
!   LOGICAL, INTENT(IN), OPTIONAL :: opt_detrend, opt_fft
!   REAL,    INTENT(IN), OPTIONAL :: opt_taper
!
! Routine to create band-pass filtered series at each lat/lon grid point.
!
! Variables:
!
!   nlon  - The longitudinal dimension
!
!   nlat  - The latitudinal dimension
!
!   ntim  - The time dimension
!
!   x     - A three dimensional variable array
!           **missing data not allowed**
!
!   xmsg  - Missing value
!
!   spd   - Sampling rate. For example: if srate refers to "samples per day",
!           then, srate is one of the following [1,2,4,8,12,24]. These correspond
!           to [24,12,6,3,2,1] hour sampling rates. Other common sampling units
!           are "samples per year" and "samples per month".
!
!   bpf   - An integer array of length 3. The first two elements contain the
!           band pass start and end times. The last element is the number of
!           weights to be used.
!
!   xts   - A 3d rray containing band-passed filtered values.
!
!   opt_detrend - Series xts will be detrended in time, if present and .TRUE
!                 Default: .FALSE.
!
!   opt_fft     - An fft will be used to perform the filtering, if present and .TRUE.
!                 Default: .FALSE.
!
!   opt_taper   - If opt_fft=.TRUE., then a "opt_taper" taper will be applied
!                 to the series prior to the fft. Default: 0.1 (10%)
!
! Notes:
!
!   At each time step, the input time series at each grid point is band-pass
!   filtered using weighted running averages or, optionally, via an FFT.
!   If the FFT option is activated, the fft coefficients will be weighted by
!   the response function returned by filwgts_lanczos.
!
!   The user must be aware that the appropriate number of filter weights is a
!   direct function of the band pass period. The shorter the period, the more
!   weights that will be required to sufficiently resolve the desired period.
!
!   The input array, x, should have sufficient temporal padding' so that the
!   filter will have its desired result over the period of interest.
!   For example, if daily mean data, spd=1, are being analyzed and bpf(2)=201,
!   then the input array should have bpf(2)/2 days padding before and after
!   the time period of focus.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_mjo_xcor_lag_season(ntim, npts, ref, x, xmsg, mxlag, ccr,&
!                                   opt_smth9)
!
!   INTEGER, INTENT(IN   ) :: ntim, npts
!   REAL,    INTENT(IN   ) :: ref(ntim), x(npts,ntim), xmsg
!   INTEGER, INTENT(IN   ) :: mxlag
!   REAL,    INTENT(  OUT) :: ccr(npts,-mxlag:mxlag)
!   REAL,    INTENT(IN), OPTIONAL :: opt_smth9
!
! Routine to calculate lagged correlations between a reference series
! and gridded data as specified by the US-CLIVAR MJO diagnostics
! website: http://climate.snu.ac.kr/mjo_diagnostics/index.htm
!
! Variables:
!
!   ntim  - Time dimension of array ref and x
!
!   npts  - Spatial (longitudinal/latitudinal) dimension (nlon/nlat)
!           of array x
!
!   ref   - Reference time series containing daily values.
!
!   x     - A two dimensional variable array.
!           Nominally, x(nlat,ntim) or x(nlon,ntim).
!
!   xmsg  - Missing value of arrays ref and x
!
!   mxlag - Maximum number of lags [mxlag=25 is suggested]
!
!   ccr   - The calculated lagged correlations
!
!   opt_smth9 - If present, it can have two values 0.25 or -0.25 to
!               perform 'heavy' or 'light' local 9-point smoothing.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_mjo_xcor_lag(ntim, npts, ref, x, xmsg, date, seaName,&
!                            mxlag, ccr, opt_smth9)
!
!   INTEGER,      INTENT(IN   ) :: ntim, npts
!   REAL,         INTENT(IN   ) :: ref(ntim), x(npts,ntim), xmsg
!   INTEGER,      INTENT(IN   ) :: date(ntim)
!   CHARACTER(*), INTENT(IN   ) :: seaName
!   INTEGER,      INTENT(IN   ) :: mxlag
!   REAL,         INTENT(  OUT) :: ccr(npts,-mxlag:mxlag)
!   REAL,         INTENT(IN   ), OPTIONAL :: opt_smth9
!
! Routine to calculate "mean seasonal" lagged correlations between
! a reference series and gridded data.
!
! Variables:
!
!   ntim    - Time dimension of array date, ref, and x
!
!   npts    - Spatial (longitudinal/latitudinal) dimension (nlon/nlat)
!             of array x
!
!   ref     - Reference time series containing daily values.
!
!   x       - A two dimensional variable array.
!             Nominally, x(nlat,ntim) or x(nlon,ntim).
!
!   xmsg    - Missing value of arrays ref and x
!
!   date    - A one-dimensional array containing the dates of time,
!             in "yyyymmdd" format
!
!   SeaName - Season name, it can have three values "winter", "summer",
!             or, "annual". If not, default is "annual"
!
!   mxlag   - Maximum number of lags [mxlag=25 is suggested]
!
!   ccr     - The calculated "mean seasonal" lagged correlations
!
!   opt_smth9 - If present, it can have two values 0.25 or -0.25 to
!               perform 'heavy' or 'light' local 9-point smoothing.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_mjo_wavenum_freq_season(nlon, ntim, x, xmsg, date, seaName, nday,&
!                                       spectra, opt_freq, opt_wave, opt_smth9)
!
!   INTEGER,      INTENT(IN   ) :: nlon, ntim
!   REAL,         INTENT(IN   ) :: x(nlon,ntim), xmsg
!   INTEGER,      INTENT(IN   ) :: date(ntim)
!   CHARACTER(*), INTENT(IN   ) :: seaName
!   INTEGER,      INTENT(IN   ) :: nday
!   REAL,         INTENT(  OUT) :: spectra(0:nday,0:nlon)
!   REAL,         INTENT(  OUT), OPTIONAL :: opt_freq(0:nday), opt_wave(0:nlon)
!   REAL,         INTENT(IN   ), OPTIONAL :: opt_smth9
!
! Routine to calculate wavenumber-frequency (space-time) spectar via
! seasonal averaging as defined by the US-CLIVAR MJO diagnostics
! website: http://climate.snu.ac.kr/mjo_diagnostics/index.htm
!
! Variables:
!
!   nlon      - The longitudinal dimension
!
!   ntim      - The time dimension
!
!   x         - Variable array containg daily mean values.
!               **missing data not allowed**
!
!   xmsg      - Missing value of array x
!
!   date      - Dates of time, in "yyyymmdd" format
!
!   SeaName   - Season name, it can have three values "winter", "summer",
!               or, "annual". If not, default is "annual"
!
!   nday      - Days of season, should be ~180 or ~365.
!               nday ~ 180/180/365 for seaName = "winter"/"summer"/"annual"
!
!   spectra   - The calculated (wavenumber x frequency) spectra.
!
!   opt_freq  - Frequency, time coordinates
!
!   opt_wave  - Wave number, space coordinates
!
!   opt_smth9 - If present, it can have two values 0.25 or -0.25 to
!               perform 'heavy' or 'light' local 9-point smoothing.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_mjo_spectra_season(nlon, nlat, ntim, x, xmsg, wy, date, seaName, nday,&
!                   smjo, smjo_spcx, smjo_frq, smjo_bw, smjo_xvari, smjo_xlag1,&
!                   opt_detrend, opt_detrend_seg, opt_smooth_seg, opt_taper_seg)
!
!   INTEGER,      INTENT(IN   ) :: nlon, nlat, ntim
!   REAL,         INTENT(IN   ) :: x(nlon,nlat,ntim), xmsg
!   REAL,         INTENT(IN   ) :: wy(nlat)
!   INTEGER,      INTENT(IN   ) :: date(ntim)
!   CHARACTER(*), INTENT(IN   ) :: seaName
!   INTEGER,      INTENT(IN   ) :: nday
!   REAL,         INTENT(  OUT) :: smjo
!   REAL,         INTENT(  OUT), OPTIONAL :: smjo_spcx(nday/2+1), smjo_frq(nday/2+1)
!   REAL,         INTENT(  OUT), OPTIONAL :: smjo_bw, smjo_xvari, smjo_xlag1
!   LOGICAL,      INTENT(IN   ), OPTIONAL :: opt_detrend
!   INTEGER,      INTENT(IN   ), OPTIONAL :: opt_detrend_seg, opt_smooth_seg
!   REAL,         INTENT(IN   ), OPTIONAL :: opt_taper_seg
!
! Routine to calculate seasonal spectra via segment averaging as
! defined by the US-CLIVAR MJO diagnostics website:
! http://climate.snu.ac.kr/mjo_diagnostics/index.htm
!
! Variables:
!
!   nlon    - The longitudinal dimension
!
!   nlat    - The latitudinal dimension
!
!   ntim    - The time dimension
!
!   x       - A three dimensional variable array
!             **missing data not allowed**
!
!   xmsg    - Missing value
!
!   wy      - A one-dimensional array containing the latitudinal weights.
!
!   date    - A one-dimensional array containing the dates of time,
!             in "yyyymmdd" format
!
!   SeaName - Season name, it can have three values "winter", "summer",
!             or, "annual". If not, default is "annual"
!
!   nday    - Days of season, should be ~180 or ~365.
!             nday ~ 180/180/365 for seaName = "winter"/"summer"/"annual"
!
!   smjo    - the calciulated degrees of freedom. Associated with the
!             following optional output arguments:
!
!             smjo_spcx  - 1D array containing the segment averaged spectra.
!
!             smjo_frq   - 1D array containing the frequencies.
!
!             smjo_bw    - band-width
!
!             smjo_xvari - average of each segment's input variance
!
!             smjo_xlag1 - average lag one day autocorrelation
!
!   opt_detrend     - Entire series will be detrended, if present with .TRUE.
!
!   opt_detrend_seg - If present, each segment will be detrended.
!                     < 0 : do no detrending.
!                     = 0 : remove series mean (minimum recommended option)
!                     = 1 : remove the series mean and lst sqrs linear trend
!                     = 2 : remove the series mean and lst sqrs quadratic trend
!                           know what you are doing before applying this option
!
!   opt_smooth_seg  - If present, each segment will be smoothed using a running
!                     average of length
!                     = 0 : do no smoothing, spcx contains raw spectral estimates
!                           (periodogram)
!                     > 0 : average jave periodogram estimates together utilizing
!                           modified daniell smoothing (good stability but may
!                           lead to large bias ). all weights are 1/jave except
!                           wgt(1) and wgt(jave) which are 1/(2*jave). this is
!                           the recommended option.
!
!   opt_taper_seg   - If present, each segment will be tapered. prior to
!                     computing the spectra. Typically, opt_taper_seg=0.1
!                     [10% of segment length].
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_mjo_cross(nlon, nlat, ntim, x, y, xmsg, ymsg, segLen,&
!                         segOverLap, stc, stc_wave, stc_freq, stc_dof,&
!                         stc_prob, stc_prob_coh2, stc_segmentLength,&
!                         stc_segmentOverLap, stc_segmentRepeat)
!
!   INTEGER, INTENT(IN   ) :: nlon, nlat, ntim
!   REAL,    INTENT(IN   ) :: x(nlon,nlat,ntim), xmsg
!   REAL,    INTENT(IN   ) :: y(nlon,nlat,ntim), ymsg
!   INTEGER, INTENT(IN   ) :: segLen, segOverLap
!   REAL,    INTENT(  OUT) :: stc(nlon+1,segLen/2+1,16)
!   REAL,    INTENT(  OUT), OPTIONAL :: stc_wave(nlon+1)
!   REAL,    INTENT(  OUT), OPTIONAL :: stc_freq(segLen/2+1)
!   REAL,    INTENT(  OUT), OPTIONAL :: stc_dof
!   REAL,    INTENT(  OUT), OPTIONAL :: stc_prob(6)
!   REAL,    INTENT(  OUT), OPTIONAL :: stc_prob_coh2(6)
!   INTEGER, INTENT(  OUT), OPTIONAL :: stc_segmentLength
!   INTEGER, INTENT(  OUT), OPTIONAL :: stc_segmentOverLap
!   INTEGER, INTENT(  OUT), OPTIONAL :: stc_segmentRepeat
!
! Routine to calculat space-time cross spectrum over multiple segments.
!
! Variables:
!
!   nlon  - The longitudinal dimension
!
!   nlat  - The latitudinal dimension
!
!   ntim  - The time dimension
!
!   x, y  - Three dimensional variable arrays dimensioned: (lom,lat,time).
!           The longitudes should be global while the latitudes should
!           only span the south-north region of interest. The size of the
!           'time' dimension should be the size of the desired segment
!           length. EG: for daily mean data, the size of the time
!           dimension is typically 96, 128, 256, etc.
!           **missing data not allowed**
!
!   xmsg  - Missing value of the array x
!
!   ymsg  - Missing value of the array y
!
!   segLen     - Length of the segment.
!
!   segOverLap - Overlap of the segment.
!
!   stc   - A three-dimensional array (wavenumber,frequency,16)
!           containing the 16 cross spectral quantities associated with
!           the specific time segment.
!
!           (:,:, 1) -  symmetric power spectrum of x
!           (:,:, 2) - asymmetric power spectrum of x
!           (:,:, 3) -  symmetric power spectrum of y
!           (:,:, 4) - asymmetric power spectrum of y
!           (:,:, 5) -  symmetric cospectrum
!           (:,:, 6) - asymmetric cospectrum
!           (:,:, 7) -  symmetric quadrature spectrum
!           (:,:, 8) - asymmetric quadrature spectrum
!
!           (:,:, 9) -  symmetric coherence-squared spectrum
!           (:,:,10) - asymmetric coherence-squared spectrum
!           (:,:,11) -  symmetric phase spectrum
!           (:,:,12) - asymmetric phase spectrum
!           (:,:,13) -  symmetric component-1 phase spectrum
!           (:,:,14) - asymmetric component-1 phase spectrum
!           (:,:,15) -  symmetric component-2 phase spectrum
!           (:,:,16) - asymmetric component-2 phase spectrum
!
! The returned variable will have the following optional arguments:
!
!   stc_segmentLength  - segment length
!   stc_segmentOverLap - segment overlap
!   stc_segmentRepeat  - repeat overlap
!   stc_dof            - degrees of freedom
!   stc_prob           - (/0.80, 0.85, 0.90, 0.925, 0.95, 0.99/)
!   stc_prob_coh2      - coherence-squared levels corresponding to prob
!
! and the following coordinate variables:
!
!   stc_wave - wave number [-M/2 to M/2 where M is the number of longitudes ]
!   stc_freq - frequencies [ 0.0 to 0.5 cycles per day ]
!
!=====================================================================
! Earth Science - Drought
!=====================================================================
!
! SUBROUTINE ng_spi(ntim, p, pmsg, nrun, spi)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_spi( ntim, p, pmsg, nrun, spi )
!
!   INTEGER, INTENT(IN   ) :: ntim
!   REAL,    INTENT(IN   ) :: p(ntim), pmsg
!   INTEGER, INTENT(IN   ) :: nrun
!   REAL,    INTENT(  OUT) :: spi(ntim)
!
! Calculates the standardized precipitation index (SPI) by fitting a
! gamma or a Pearson Type III distribution to monthly precipitation values.
!
! compute SPI: Standardized Precipitation Index using gamma distribution
!
! Variables:
!
!  p    - Monthly precipitation
!
!  pmsg - Missing value
!
!  nrun - The number of months over which the SPI index is to be
!         calculated. Common values are 3, 6, 12, 24,36.
!
!  spi  - Calculated standardized precipitation index
!
!  ntim - Dimension of p and spi
!
!=====================================================================
! Earth Science - Meteorology
!=====================================================================
!
! SUBROUTINE ng_zonal_mpsi(nlon, nlat, nlev, lat, p, PS, V, msg, ZM_MPSI)
!
! SUBROUTINE ng_pot_vort_isobaric(nlon, nlat, nlev, p, u, v, t, ylat, grid, pv,&
!                                 s, theta, dthdp, dudp, dvdp, dtdx, dtdy)
!
! SUBROUTINE ng_pot_vort_hybrid  (nlon, nlat, nlev, p, u, v, t, ylat, grid, pv,&
!                                 s, theta, dthdp, dudp, dvdp, dthdx, dthdy)
!
! ELEMENTAL REAL FUNCTION ng_pot_temp(p, t)
!
! SUBROUTINE ng_static_stability(n, p, t, s, theta, dthdp)
!
! SUBROUTINE ng_grad_latlon_cfd(nlon, nlat, xlon, ylat, z, zmsg, cyclic, dzdx, dzdy)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_zonal_mpsi(nlon, nlat, nlev, lat, p, PS, V, msg, ZM_MPSI)
!
!   INTEGER, INTENT(IN   ) :: nlon, nlat, nlev
!   REAL,    INTENT(IN   ) :: lat(nlat), p(nlev), PS(nlon,nlat)
!   REAL,    INTENT(IN   ) :: V(nlon,nlat,nlev), msg
!   REAL,    INTENT(  OUT) :: ZM_MPSI(nlat,nlev)
!
!    DESCRIPTION: Computes a ZONAL MEAN MERIDIONAL STREAM FUNCTION using a
!                 modified definition of the CCM Processor zonal mean
!                 meridional stream function. The modified definition used
!                 here is given by
!
!                                                           / PS
!                                                          |
!                                          2 pi a cos(lat) |  _
!                    ZM_MPSI(lat,lev)  =   --------------- |  V(lat,lev) dp
!                                                g         |
!                                                          |
!                                                         / p
!
!                       _
!                 where V is the zonal mean meridional wind, p pressure, PS
!                 surface pressure, a the radius of the earth, and g the
!                 acceleration of gravity. The coordinate dimensions are given
!                 by lon, the longitude dimension, lat, the latitude dimension,
!                 and lev, the pressure level dimension.
!
!      REFERENCE: Buja, L. E. (1994) CCM Processor User's Guide (Unicos
!                 Version). NCAR Technical Note NCAR/TN-384+IA, pages B-17
!                 to B-18.
!
!      INVOKE AS:
!
!             CALL CCMP_ZM_MSPI( nlon, nlat, nlev, V, lat, p, PS, msg, ZM_MPSI )
!
!     INPUT ARGS:
!
!           nlon: Number of longitudes of longitude dimension. Type INTEGER.
!           nlat: Number of latitudes of latitude dimension. Type INTEGER.
!           nlev: Number of levels of pressure level dimension. Type
!                 INTEGER.
!              V: Three-dimensional (lon,lat,lev) array of meridional wind
!                 values in which THE PRESSURE LEVEL DIMENSION MUST BE ORDERED
!                 TOP TO BOTTOM. Units must be m s^-1. Type REAL.
!                                            _
!                 (The zonal mean of V, i.e. V, will be computed in this sub-
!                 routine in allocated memory.)
!            lat: One-dimensional array of latitude values of latitude dimension
!                 in degrees. Type REAL.
!              p: One-dimensional array of pressure level values of vertical
!                 dimension ORDERED TOP TO BOTTOM. Units must be Pa. Type REAL.
!                 The first value must be greater than 500 Pa (5mb), and the
!                 last value must be less than 100500 Pa (1005mb).
!             PS: Two-dimensional (lon,lat) array of surface pressures. Units
!                 must be Pa. Type REAL.
!
!            msg: Missing value (fill value) of stream function where V occurs
!                 entirely below the earth's surface for all longitudes at fixed
!                 latitude and pressure level. Type REAL.
!
!    OUTPUT ARGS:
!
!        ZM_MPSI: Two-dimensional (lat,lev) array of zonal mean meridional
!                 stream function values in which the first dimension is lati-
!                 tude and the second dimension is pressure level. THE PRESSURE
!                 LEVEL DIMENSION IS ORDERED TOP TO BOTTOM UPON RETURN. Missing
!                 values (msg) are assigned to ZM_MPSI where V occurs below
!                 ground for all longitudes at fixed latitude and pressure level.
!                 Units are kg s^-1. Type REAL.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_pot_vort_isobaric(nlon, nlat, nlev, p, u, v, t, ylat, grid, pv,&
!                                 s, theta, dthdp, dudp, dvdp, dtdx, dtdy)
!
!   INTEGER, INTENT(IN   ) :: nlon, nlat, nlev
!   REAL,    INTENT(IN   ) ::           p    (          nlev)
!   REAL,    INTENT(IN   ) ::           u    (nlon,nlat,nlev)
!   REAL,    INTENT(IN   ) ::           v    (nlon,nlat,nlev)
!   REAL,    INTENT(IN   ) ::           t    (nlon,nlat,nlev)
!   REAL,    INTENT(IN   ) ::           ylat (     nlat     )
!   INTEGER, INTENT(IN   ) :: grid
!   REAL,    INTENT(  OUT) ::           pv   (nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: s    (nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: theta(nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: dthdp(nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: dudp (nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: dvdp (nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: dtdx (nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: dtdy (nlon,nlat,nlev)
!
! Routine to compute Potential Vorticity on constant pressure levels and
! a "global" rectilinear grid. (The reason for the global grid is that
! highly accurate spherical harmonic functions are used to compute
! horizontal gradients)
!
! Reference:
! Bluestein: Synoptic-Dynamic Meteorology in Midlatitudes
!            Bug reported by Andy Show (Dec 2015)
!            pg 264  Eq 4.5.93 with [ (R/(s*p) ] replaced by [ 1/s ])
!            R/(s*p) = (R/p)(p/(R*T*d(theta)/dp) = 1/(T*d(theta)/dp ]= 1/s
!
! Variables:
!
!     nlon  - first dimension,  longitude
!     nlat  - second dimension, latitudes
!     nlev  - third dimension,  levels
!
!     p     - pressure levels            (Pa)  [1D]
!
!     u     - zonal wind components      (m/s) [3D]
!
!     v     - meridional wind components (m/s) [3D]
!
!     t     - temperature                (K)   [3D]
!
!     ylat  - latitudes, must be ordered south to north
!
!     grid  - grid type
!             =0 means gaussian grid
!             =1 means regular/fixed grid
!
!---------
! Note: u,v,t MUST be SOUTH-TO-NORTH
!       and must be GLOBAL because spherical harmonics are used
!---------
!
!     pv    - potential vorticity   (K m2/kg/s)
!
!     s     - static stability      (K/Pa)
!
!     theta - potential temperature (K)
!
!     dthdp - d(theta)/dp           (K/Pa)
!
!     dudp  - vertical (pressure) derivatives of u
!
!     dvdp  - vertical (pressure) derivatives of v
!
!     dtdx  - longitud temperature gradients (K/m)
!
!     dtdy  - latitude temperature gradients (K/m)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_pot_vort_hybrid(nlon, nlat, nlev, p, u, v, t, ylat, grid, pv,&
!                               s, theta, dthdp, dudp, dvdp, dthdx, dthdy)
!
!   INTEGER, INTENT(IN   ) :: nlon, nlat, nlev
!   REAL,    INTENT(IN   ) ::           p    (nlon,nlat,nlev)
!   REAL,    INTENT(IN   ) ::           u    (nlon,nlat,nlev)
!   REAL,    INTENT(IN   ) ::           v    (nlon,nlat,nlev)
!   REAL,    INTENT(IN   ) ::           t    (nlon,nlat,nlev)
!   REAL,    INTENT(IN   ) ::           ylat (     nlat     )
!   INTEGER, INTENT(IN   ) :: grid
!   REAL,    INTENT(  OUT) ::           pv   (nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: s    (nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: theta(nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: dthdp(nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: dudp (nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: dvdp (nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: dthdx(nlon,nlat,nlev)
!   REAL,    INTENT(  OUT), OPTIONAL :: dthdy(nlon,nlat,nlev)
!
! Routinr to compute Isentropic Potential Vorticity on hybrid levels and
! a "global" rectilinear grid. (The reason for the global grid is that
! highly accurate spherical harmonic functions are used to compute
! horizontal gradients)
!
! Reference:
! CCM Processor User's Guide: May 1994: page B-19
! Original source P Rasch and B Boville
!
! Variables:
!
!     nlon  - first dimension,  longitude
!     nlat  - second dimension, latitudes
!     nlev  - third dimension,  levels
!
!     p     - pressure levels            (Pa)  [3D]
!
!     u     - zonal wind components      (m/s) [3D]
!
!     v     - meridional wind components (m/s) [3D]
!
!     t     - temperature                (K)   [3D]
!
!     ylat  - latitudes, must be ordered south to north
!
!     grid  - grid type
!             =0 means gaussian grid
!             =1 means regular/fixed grid
!
!---------
! Note: p,u,v,t MUST be SOUTH-TO-NORTH
!       and must be GLOBAL because spherical harmonics are used
!---------
!
!     pv    - potential vorticity   (K m2/kg/s)
!
!     s     - static stability      (K/Pa)
!
!     theta - potential temperature (K)
!
!     dthdp - d(theta)/dp           (K/Pa)
!
!     dudp  - vertical (pressure) derivatives of u
!
!     dvdp  - vertical (pressure) derivatives of v
!
!     dthdx - longitud potential temperature gradients (K/m)
!
!     dthdy - latitude potential temperature gradients (K/m)
!
!---------------------------------------------------------------------
!
! ELEMENTAL REAL FUNCTION ng_pot_temp(p, t)
!
! Routine to compute potential temperature
!
! Nomenclature
!
! p - pressure levels (units is Pa)
!
! t - temperature (units is K)
!
! ng_pot_temp - potential temperature (units is K)
!
!     Also: equivalent temperature (teqv) could be input
!     teqv =  temperature of an air parcel from which all the water vapor
!             has been extracted by an adiabatic process.
!     teqv = t + (Lv/cpd)*r  ;
!     cpd  = 1004. or 1005.7 ; specific heat dry air [J/kg/K]
!     Lv   = 2.5104e6        ; [J/kg]=[m2/s2]  Latent Heat of Vaporization of Water
!     r    = mixing ratio
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_static_stability(n, p, t, s, theta, dthdp)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: p(n), t(n)
!   REAL,    INTENT(  OUT) :: s(n)
!   REAL,    INTENT(  OUT), OPTIONAL :: theta(n), dthdp(n)
!
! Routine to compute static stability
!
! Reference:
! Bluestein (1992): Synoptic-Dynamic Meteorology in Midlatitudes
!                   pg 197, eqn=4.3.8
!
!                   s = -t*d[log(theta)]/dp = -(t/theta)*d(theta)/dp
!
! Variables:
!
! n - dimension of arrays p, t, s, theta, and dthdp
!
! p - pressure levels (units is Pa)
!
! t - temperature (units is K)
!
!     Also: equivalent temperature (teqv) could be input
!     teqv = temperature of an air parcel from which all the water vapor
!            has been extracted by an adiabatic process.
!     teqv = t + (Lv/cpd)*r  ;
!     cpd  = 1004. or 1005.7 ; specific heat dry air [J/kg/K]
!     Lv   = 2.5104e6        ; [J/kg]=[m2/s2]  Latent Heat of Vaporization of Water
!     r    = mixing ratio    ; (kg/kg)
!
! s - static stability (units is K/Pa)
!
! theta - potential temperature (units is K)
!
! dthdp - d(theta)/dp (units is K/Pa)
!
! Note: In a statically stable atmosphere: d(theta)/dp < 0, hence s > 0
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_grad_latlon_cfd(nlon, nlat, z, xlon, ylat, zmsg, cyclic, dzdx, dzdy)
!   INTEGER, INTENT(IN   ) :: nlon, nlat
!   REAL,    INTENT(IN   ) :: z(nlon,nlat), xlon(nlon), ylat(nlat), zmsg
!   LOGICAL, INTENT(IN   ) :: cyclic
!   REAL,    INTENT(  OUT) :: dzdx(nlon,nlat), dzdy(nlon,nlat)
!
! Routine to Compute the meridional (ylat) and zonal (xlon) gradients
! of a variable (z) on a global or limited area rectilinear grid.
!
! nlon:   The first dimension (the longitudinal dir) of array z
!
! nlat:   The second dimension (the latitudinal dir) of array z
!
! z:      Variable of 2-dimensions, size of (nlon,nlat)
!
! xlon:   A one-dimensional array containing the longitudes in degrees east.
!         These must be in increasing order and must be equally spaced.
!
! ylat:   A one-dimensional array containing the latitudes in degrees north.
!         These need not be equally spaced. For example they can be gaussian
!         latitudes.
!
! zmsg:   Missing value of variable z
!
! cyclic: True: z treated as cyclic in xlon and the end values and all
!         the returned values will be calculated via centered differences.
!         False: z NOT treated as cyclic in xlon and the end values will
!         use a one-sided difference scheme for the end points.
!         z should not include a cyclic point.
!
! dzdx:   The computed zonal gradient, d(z)/d(xlon), size of (nlon,nlat)
!
! dzdy:   The computed meridional gradient, d(z)/d(ylat), size of (nlon,nlat)
!
!=====================================================================
! Earth Science - Oceanography
!=====================================================================
!
! FUNCTION ng_rho_mwjf(nx, ny, t2d, s2d, spv, depth) RESULT(rho)
!
!---------------------------------------------------------------------
!
! FUNCTION ng_rho_mwjf( nx, ny, t2d, s2d, spv, depth ) RESULT( rho )
!
!   INTEGER, INTENT(IN   ) :: nx, ny
!   REAL,    INTENT(IN   ) :: t2d(nx,ny), s2d(nx,ny), spv
!   REAL,    INTENT(IN   ) :: depth
!   REAL                   :: rho(nx,ny)
!
! Function to compute ocean water density given a specified range for
! potential temperature (deg Celsius) and salinity (psu).
!
! Variables:
!
!   t2d   - A 2-d array of temperature values (must be deg C).
!
!   s2d   - A 2-d array of the same size as t2d containing salinity
!           values (must be psu).
!
!   spv   - Missing value (special value) of t2d/s2d arrays
!
!   depth - A scalar value for depth at which to compute density (meters).
!
!=====================================================================
! Earth Science - WRF
!=====================================================================
!
! SUBROUTINE ng_wrf_dbz(nlon, nlat, nlev, p, t, qv, qr, qs, qg, ivarint, iliqskin, DBZ)
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_wrf_dbz(nlon, nlat, nlev, p, t, qv, qr, qs, qg, ivarint, iliqskin, DBZ)
!
!   INTEGER, INTENT(IN   ) :: nlon, nlat, nlev
!   REAL,    INTENT(IN   ) :: p (nlon,nlat,nlev)
!   REAL,    INTENT(IN   ) :: t (nlon,nlat,nlev)
!   REAL,    INTENT(INOUT) :: qv(nlon,nlat,nlev) ! will be forced to 0.0 or greater
!   REAL,    INTENT(INOUT) :: qr(nlon,nlat,nlev) ! will be forced to 0.0 or greater
!   REAL,    INTENT(INOUT) :: qs(nlon,nlat,nlev) ! will be forced to 0.0 or greater
!   REAL,    INTENT(INOUT) :: qg(nlon,nlat,nlev) ! will be forced to 0.0 or greater
!   INTEGER, INTENT(IN   ) :: ivarint, iliqskin
!   REAL,    INTENT(  OUT) :: DBZ(nlon,nlat,nlev)
!
! Routine to calculate simulated equivalent radar reflectivity factor
! [dBZ] from WRF model output.
!
! Variables:
!
!   nlon     - x-longitude (westto east) dimension
!
!   nlat     - y-latitude (south to north) dimension
!
!   vlev     - z-level (bottom to top) dimension
!
!   p        - Full pressure (perturbation + base state pressure).
!              Units must be [Pa].
!
!   t        - Temperature in [K]. This variable can be calculated by wrf_tk.
!
!   qv       - Water vapor mixing ratio in [kg/kg].
!
!   qr       - Rain mixing ratio in [kg/kg].
!
!   qs       - Snow mixing ratio in [kg/kg]. If not available, set to zero.
!
!   qg       - Graupel mixing ratio in [kg/kg]. If not available, set to zero.
!
!   ivarint  - option for the behavior of intercept parameters for the size
!              distributions of rain, snow, and graupel. See description below.
!
!              If ivarint=0, the intercept parameters are assumed constant
!              (as in MM5's Reisner-2 bulk microphysical scheme).
!
!              If ivarint=1, variable intercept parameters are used as in more
!              recent version of Reisner-2 (based on Thompson, Rasmussen, and
!              Manning, 2004, Monthly weather Review, Vol. 132, No. 2, pp. 519-542.)
!
!   iliqskin - option for scattering.
!              If set to 1, frozen particles that are at a temperature above
!              freezing will be assumed to scatter as a liquid particle.
!              Set to 0 otherwise.
!
!   DBZ      - equivalent radar reflectivity factor (Ze), based on the mixing
!              ratios of rain, snow, and graupel (if available)
!
!=====================================================================
! others
!=====================================================================
!
! FUNCTION ng_fspan( start, finish, npts )
!
! SUBROUTINE ng_nice_mnmxintvl( cmin, cmax, max_steps, outside, cmn, cmx, cis, ncl, clev, clab )
!
! SUBROUTINE ng_nice_label1( cmn, cmx, cis, nfl, clab, ncl, clev )
! SUBROUTINE ng_nice_label2( ncl, clev, nfl, clab )
!
! SUBROUTINE ng_convexhull_2d(x, y, n, vertex, nvert)
!
! SUBROUTINE ng_span_two_named_colors(namedcolor1, namedcolor2, ncolors, rgb)
! SUBROUTINE ng_span_named_colors(n_named, named_colors, rgb, ncolors, NumColorsInTable, NumColorsInRange)
!
! SUBROUTINE ng_eemd   ( n, x, nrep, noise, nimf, y, S_number, num_siftings, rng_seed ) for NAG/GNU/G95 only
! SUBROUTINE ng_ceemdan( n, x, nrep, noise, nimf, y, S_number, num_siftings, rng_seed ) for NAG/GNU/G95 only
!
!---------------------------------------------------------------------
!
! FUNCTION ng_fspan( start, finish, npts )
!
!   REAL,    INTENT(IN) :: start, finish
!   INTEGER, INTENT(IN) :: npts
!   REAL                :: ng_fspan(npts)
!
! Function to return a 1D array with npts equally-spaced points
! from start to finish, inclusive.
!
! Variables:
!
!   start  - Value at which to start.
!
!   finish - Value at which to end.
!
!   npts   - Number of equally-spaced points desired between start
!            and finish. This value must be >= 2.
!
! Note: Executable created by "Silverfrost" non-optimizing compilation
!       may have trouble to invoking this function at runtime.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_nice_mnmxintvl( cmin, cmax, max_steps, outside,&
!                               cmn, cmx, cis, ncl, clev, clab )
!   IMPLICIT NONE
!
!   REAL,         INTENT(IN   )           :: cmin, cmax
!   INTEGER,      INTENT(IN   )           :: max_steps
!   LOGICAL,      INTENT(IN   )           :: outside
!   REAL,         INTENT(  OUT)           :: cmn, cmx, cis
!   INTEGER,      INTENT(  OUT), OPTIONAL :: ncl
!   REAL,         INTENT(  OUT), OPTIONAL :: clev(max_steps)
!   CHARACTER(*), INTENT(  OUT), OPTIONAL :: clab(max_steps)
!
! Given the minimum (cmin) and maximum (cmax) values of a data domain
! and the maximum number of levels desired (max_steps), this subroutine
! calculates "nice" values for endpoints and spacing (cmn, cmx, cis).
!
! The outside flag (outside) controls whether the returned "nice" min
! and max values are inside or outside the data range.
!
! This routine can also create arrays (with length ncl) of "nice"
! equally-spaced levels (clev) and its labels (clab) through the
! data domain.
!
! Variables:
!
!   cmin      - the minimum value of the domain
!
!   cmax      - the maximum value of the domain
!
!   max_steps - the maximum number of steps desired
!
!   outside   - controls whether return cmn/cmx fall
!               just outside or just inside the data domain.
!
!               if outside:
!                   cmn <= cmin < cmn+cis
!                   cmx >= cmax > cmx-cis
!               if inside:
!                   cmn >= cmin > cmn-cis
!                   cmx <= cmax < cmx+cis
!
!   cmn       - the "nice" minimum
!
!   cmx       - the "nice" maximum
!
!   cis       - the "nice" interval (spacing)
!
!   ncl       - the number of "nice" levels
!
!               ncl == 1 + NINT((cmx-cmn)/cis) <= max_steps
!
!   clev      - the levels array (at least ncl elements)
!
!               clev(1:ncl) = (/cmn, cmn+cis, cmn+2*cis, ..., cmn+(ncl-1)*cis/)
!
!   clab      - the labels (character format of clev) array
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_nice_label1( cmn, cmx, cis, nfl, clab, ncl, clev )
!   IMPLICIT NONE
!
!   REAL,         INTENT(IN   )           :: cmn, cmx, cis
!   INTEGER,      INTENT(IN   )           :: nfl
!   CHARACTER(*), INTENT(  OUT)           :: clab(1+NINT((cmx-cmn)/cis))
!   INTEGER,      INTENT(  OUT), OPTIONAL :: ncl
!   REAL,         INTENT(  OUT), OPTIONAL :: clev(1+NINT((cmx-cmn)/cis))
!
! Routine to create levels and labels arrays (ncl, clev and clab) for
! the equally-spaced levels through the given domain described by
! two endpoints and spacing (cmn, cmx, cis)
!
! Variables:
!
!   cmn  - the minimum value of the domain
!
!   cmx  - the maximum value of the domain
!
!   cis  - the spacing
!
!   clab - the "nice" labels array for levels calculated as
!          (/cmn, cmn+cis, cmn+2*cis, ..., cmn+(n-1)*cis/)
!          with n = 1+NINT((cmx-cmn)/cis)
!
!          Labels are written in ordinary REAL format: (-) (I) (.) (F)
!
!            "-" is the sign for negative values
!            "I" is the integer portion
!            "." is the decimal point
!            "F" is the fractional portion
!
!   nfl  - the maximum length of F
!
!          If nfl <= 0, (F) and the decimal point (.) is omitted.
!
!   ncl  - the number of levels
!
!          ncl == 1 + NINT((cmx-cmn)/cis)
!
!   clev - the levels array
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_nice_label2( ncl, clev, nfl, clab )
!
!   INTEGER,      INTENT(IN   ) :: ncl
!   REAL,         INTENT(IN   ) :: clev(ncl)
!   INTEGER,      INTENT(IN   ) :: nfl
!   CHARACTER(*), INTENT(  OUT) :: clab(ncl)
!
! Routine to create labels array (clab) for the given levels array.
!
! Variables:
!
!   ncl  - the size of arrays clev and clab
!
!   clev - the levels array
!
!   clab - the "nice" labels array
!
!          Labels are written in ordinary REAL format: (-) (I) (.) (F)
!
!            "-" is the sign for negative values
!            "I" is the integer portion
!            "." is the decimal point
!            "F" is the fractional portion
!
!   nfl  - the maximum length of F
!
!          If nfl <= 0, (F) and the decimal point (.) is omitted.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_convexhull_2d(x, y, n, vertex, nvert)
!
!   INTEGER, INTENT(IN   ) :: n
!   REAL,    INTENT(IN   ) :: x(n), y(n)
!   INTEGER, INTENT(  OUT) :: vertex(n), nvert
!
! Find the vertices (in counterclockwise order) of a polygon enclosing
! the points (x(i), y(i), i=1, ..., n).
!
! On output, vertex(i), i=1, ..., nvert contains the numbers of the
! vertices that form the convex hull.
!
! Ref: Alan Miller: http://jblevins.org/mirror/amiller/envelope.f90
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_span_named_colors(n_named, named_colors, rgb, ncolors,&
!                                 NumColorsInTable, NumColorsInRange)
!
!   INTEGER,      INTENT(IN   ) :: n_named
!   CHARACTER(*), INTENT(IN   ) :: named_colors(n_named)
!   REAL,         INTENT(  OUT) :: rgb(3,256)
!   INTEGER,      INTENT(  OUT) :: ncolors
!   INTEGER, INTENT(IN), OPTIONAL :: NumColorsInTable
!   INTEGER, INTENT(IN), OPTIONAL :: NumColorsInRange(n_named-1)
!
! Given a list of named colors, this subroutine creates a series of
! RGB triplets that creates a span between each set of colors.
!
! By default, a color table with 256 or fewer colors is returned, with
! an equal number of colors between each set of named colors.
!
! The optional arguments can be used to set the following options:
!
!   NumColorsInTable
!      Maximun number of colors to put in the color table.
!      Must be <= 256 and >= # of named colors (n_named) specified
!
!   NumColorsInRange
!      Number of colors (>=2) to span between each set of
!      named colors. For example, if you specify four
!      colors (/"red", "green", "blue","purple"/), and
!      NumColorsInRange of (/5, 8, 4/), then you'll have
!      a color table (5+8+4-2=15 colors) with:
!
!      1        5          12        15
!      red......green......blue......purple
!
! Note: argument "ncolors" returns the actual colors created
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_span_two_named_colors(namedcolor1, namedcolor2, ncolors, rgb)
!
!   CHARACTER(*), INTENT(IN   ) :: namedcolor1, namedcolor2
!   INTEGER,      INTENT(IN   ) :: ncolors
!   REAL,         INTENT(  OUT) :: rgb(3,ncolors)
!
! Routine to create a series of RGB triplets that spans between the
! two given named colors.
!
! Note: The number (ncolors) includes both two end named colors.
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_eemd(n, x, nrep, noise, nimf, y, S_number, num_siftings, rng_seed)
!
!   INTEGER, INTENT(IN   )           :: n
!   REAL,    INTENT(IN   )           :: x(n)
!   INTEGER, INTENT(IN   )           :: nrep
!   REAL,    INTENT(IN   )           :: noise
!   INTEGER, INTENT(IN   )           :: nimf
!   REAL,    INTENT(  OUT)           :: y(n,nimf)
!   INTEGER, INTENT(IN   ), OPTIONAL :: S_number
!   INTEGER, INTENT(IN   ), OPTIONAL :: num_siftings
!   INTEGER, INTENT(IN   ), OPTIONAL :: rng_seed
!
! Routine to perform ensemble empirical mode decomposition (EEMD).
!
! Note: Only for NAG/GNU/G95 Fortran compilers currently
!
! Variables:
!
!   n     - Size of input signal array
!
!   x     - Input signal array
!
!   nrep  - Number of replications (ensemble size) members to be used
!
!   noise - Standard deviation of the Gaussian random numbers used as
!           additional noise. This value is relative to the standard
!           deviation of the input signal.
!
!   nimf  - Number of Intrinsic Mode Functions (IMFs) to compute.
!
!           An appropriate value, NINT(LOG10(REAL(n))/LOG10(2.0)), may
!           be used. This corresponds to a maximal number of IMFs.
!
!           Note that the final residual is also counted as an IMF in
!           this respect, so you most likely want at least nimf=2
!
!   y     - the calculated IMF (Intrinsic Mode Functions) arrays
!
!---------
!
!   S_number - Use the S-number to specify stopping criterion for the
!              EMD procedure Typical values are in the range 3-8.
!
!              If S_number is zero, this stopping criterion is ignored.
!
!              Default is 4
!
!   num_siftings - Use a maximum number of siftings as a stopping
!              criterion. If num_siftings is zero, this stopping
!              criterion is ignored.
!
!              Default is 50
!
!   rng_seed - A seed for the random number generator. A value of zero
!              denotes an implementation-defined default value.
!
!              Default is 0
!
!---------------------------------------------------------------------
!
! SUBROUTINE ng_ceemdan(n, x, nrep, noise, nimf, y, S_number, num_siftings, rng_seed)
!
!   INTEGER, INTENT(IN   )           :: n
!   REAL,    INTENT(IN   )           :: x(n)
!   INTEGER, INTENT(IN   )           :: nrep
!   REAL,    INTENT(IN   )           :: noise
!   INTEGER, INTENT(IN   )           :: nimf
!   REAL,    INTENT(  OUT)           :: y(n,nimf)
!   INTEGER, INTENT(IN   ), OPTIONAL :: S_number
!   INTEGER, INTENT(IN   ), OPTIONAL :: num_siftings
!   INTEGER, INTENT(IN   ), OPTIONAL :: rng_seed
!
! Routine to perform Complete Ensemble Empirical Mode Decomposition
! with Adaptive Noise (CEEMDAN).
!
! Note: Only for NAG/GNU/G95 Fortran compilers currently
!
! Variables:
!
!   n     - Size of input signal array
!
!   x     - Input signal array
!
!   nrep  - Number of replications (ensemble size) members to be used
!
!   noise - Standard deviation of the Gaussian random numbers used as
!           additional noise. This value is relative to the standard
!           deviation of the input signal.
!
!   nimf  - Number of Intrinsic Mode Functions (IMFs) to compute.
!
!           An appropriate value, NINT(LOG10(REAL(n))/LOG10(2.0)), may
!           be used. This corresponds to a maximal number of IMFs.
!
!           Note that the final residual is also counted as an IMF in
!           this respect, so you most likely want at least nimf=2
!
!   y     - the calculated IMF (Intrinsic Mode Functions) arrays
!
!---------
!
!   S_number - Use the S-number to specify stopping criterion for the
!              EMD procedure Typical values are in the range 3-8.
!
!              If S_number is zero, this stopping criterion is ignored.
!
!              Default is 4
!
!   num_siftings - Use a maximum number of siftings as a stopping
!              criterion. If num_siftings is zero, this stopping
!              criterion is ignored.
!
!              Default is 50
!
!   rng_seed - A seed for the random number generator. A value of zero
!              denotes an implementation-defined default value.
!
!              Default is 0
!
!---------------------------------------------------------------------