|
NCEPLIBS-sp
2.5.0
|
The spectral transform library splib, developed in the 1990s, contains FORTRAN subprograms to be used for a variety of spectral transform functions. Supported compilers include GCC, Intel Classic, Intel OneAPI, and the NVIDIA HPC SDK.
The library has been optimized for the CRAY machines, taking full advantage of both the vector and parallel capabilities. The library is particularly efficient when transforming many fields at one time. Some entry points will diagnose the environmental number of CPUs available, but others require the number of CPUs used be specified.
The library can handle both scalar and two-dimensional vector fields. Each vector field will be represented in spectral space appropriately by its respective spherical divergence and curl (vorticity), thus avoiding the pole problems associated with representing components separately.
Some of the functions performed by the library are spectral interpolations between two grids, spectral truncations in place on a grid, and basic spectral transforms between grid and wave space. Only global Gaussian or global equidistant cylindrical grids are allowed for transforming into wave space. There are no such restricitions on grids for transforming from wave space. However, there are special fast entry points for transforming wave space to polar stereographic and Mercator grids as well as the aforementioned cylindrical grids.
The indexing of the cylindrical transform grids is totally general. The grids may run north to south or south to north; they may run east to west or west to east; they may start at any longitude as long as the prime meridian is on the grid; they may be dimensioned in any order (e.g. (i,j,k), (k,j,i), (i,k,nfield,j), etc.). Furthermore, the transform may be performed on only some of the latitudes at one time as long as both hemisphere counterparts are transformed at the same time (as in the global spectral model). The grid indexing will default to the customary global indexing, i.e. north to south, east to west, prime meridian as first longitude, and (i,j,k) order.
The wave space may be either triangular or rhomboidal in shape. Its internal indexing is strictly "IBM order", i.e. zonal wavenumber is the slower index with the real and imaginary components always paired together. The imaginary components of all the zonally symmetric modes should always be zero, as should the global mean of any divergence and vorticity fields. The stride between the start of successive wave fields is general, defaulting to the computed length of each field.
It should be noted that some routines may behave poorly or unpredictably when using 4-byte reals (libsp_4). In some routines, small numerical differences can be amplified into noticeable differences in output field values. Some applications may therefore benefit from the use of 8-byte reals (libsp_d).
This documentation is divided into 3 chapters. Chapter I is this introduction. Chapter II is a list of all entry points. Chapter III is a set of examples.
Spectral interpolations or truncations between grid and grid
| Name | Function |
|---|---|
| sptrun() | SPECTRALLY TRUNCATE GRIDDED SCALAR FIELDS |
| sptrunv() | SPECTRALLY TRUNCATE GRIDDED VECTOR FIELDS |
| sptrung() | SPECTRALLY INTERPOLATE SCALARS TO STATIONS |
| sptrungv() | SPECTRALLY INTERPOLATE VECTORS TO STATIONS |
| sptruns() | SPECTRALLY INTERPOLATE SCALARS TO POLAR STEREO |
| sptrunsv() | SPECTRALLY INTERPOLATE VECTORS TO POLAR STEREO |
| sptrunm() | SPECTRALLY INTERPOLATE SCALARS TO MERCATOR |
| sptrunmv() | SPECTRALLY INTERPOLATE VECTORS TO MERCATOR |
Spectral transforms between wave and grid
| Name | Function |
|---|---|
| sptran() | PERFORM A SCALAR SPHERICAL TRANSFORM |
| sptranv() | PERFORM A VECTOR SPHERICAL TRANSFORM |
| sptrand() | PERFORM A GRADIENT SPHERICAL TRANSFORM |
| sptgpt() | TRANSFORM SPECTRAL SCALAR TO STATION POINTS |
| sptgptv() | TRANSFORM SPECTRAL VECTOR TO STATION POINTS |
| sptgptd() | TRANSFORM SPECTRAL TO STATION POINT GRADIENTS |
| sptgps() | TRANSFORM SPECTRAL SCALAR TO POLAR STEREO |
| sptgpsv() | TRANSFORM SPECTRAL VECTOR TO POLAR STEREO |
| sptgpsd() | TRANSFORM SPECTRAL TO POLAR STEREO GRADIENTS |
| sptgpm() | TRANSFORM SPECTRAL SCALAR TO MERCATOR |
| sptgpmv() | TRANSFORM SPECTRAL VECTOR TO MERCATOR |
| sptgpmd() | TRANSFORM SPECTRAL TO MERCATOR GRADIENTS |
Spectral transform utilities
| Name | Function |
|---|---|
| spgget() | GET GRID-SPACE CONSTANTS |
| spwget() | GET WAVE-SPACE CONSTANTS |
| splat() | COMPUTE LATITUDE FUNCTIONS |
| speps() | COMPUTE UTILITY SPECTRAL FIELDS |
| splegend() | COMPUTE LEGENDRE POLYNOMIALS |
| spanaly() | ANALYZE SPECTRAL FROM FOURIER |
| spsynth() | SYNTHESIZE FOURIER FROM SPECTRAL |
| spdz2uv() | COMPUTE WINDS FROM DIVERGENCE AND VORTICITY |
| spuv2dz() | COMPUTE DIVERGENCE AND VORTICITY FROM WINDS |
| spgradq() | COMPUTE GRADIENT IN SPECTRAL SPACE |
| splaplac() | COMPUTE LAPLACIAN IN SPECTRAL SPACE |
Example 1. Interpolate heights and winds from a latlon grid to two antipodal polar stereographic grids. Subprograms GETGB and PUTGB from w3lib are referenced.
c unit number 11 is the input latlon grib file
c unit number 31 is the input latlon grib index file
c unit number 51 is the output northern polar stereographic grib file
c unit number 52 is the output southern polar stereographic grib file
c nominal spectral truncation is r40
c maximum input gridsize is 360x181
c maximum number of levels wanted is 12
parameter(lug=11,lui=31,lun=51,lus=52)
parameter(iromb=1,maxwv=40,jf=360*181,kx=12)
integer kp5(kx),kp6(kx),kp7(kx)
integer kpo(kx)
data kpo/1000,850,700,500,400,300,250,200,150,100,70,50/
c height
km=12
kp5=7
kp6=100
kp7=kpo
call gs65(lug,lui,lun,lus,jf,km,kp5,kp6,kp7,iromb,maxwv)
c winds
km=12
kp5=33
kp6=100
kp7=kpo
call gv65(lug,lui,lun,lus,jf,km,kp5,kp6,kp7,iromb,maxwv)
c
stop
end
c
subroutine gs65(lug,lui,lun,lus,jf,km,kp5,kp6,kp7,iromb,maxwv)
c interpolates a scalar field using spectral transforms.
integer kp5(km),kp6(km),kp7(km)
c output grids are 65x65 (381 km true at latitide 60).
c nh grid oriented at 280E; sh grid oriented at 100E.
parameter(nph=32,nps=2*nph+1,npq=nps*nps)
parameter(true=60.,xmesh=381.e3,orient=280.)
parameter(rerth=6.3712e6)
parameter(pi=3.14159265358979,dpr=180./pi)
real gn(npq,km),gs(npq,km)
integer jpds(25),jgds(22),kpds(25,km),kgds(22,km)
logical lb(jf)
real f(jf,km)
c
g2=((1.+sin(abs(true)/dpr))*rerth/xmesh)**2
r2=2*nph**2
rlatn1=dpr*asin((g2-r2)/(g2+r2))
rlonn1=mod(orient+315,360.)
rlats1=-rlatn1
rlons1=mod(rlonn1+270,360.)
jpds=-1
do k=1,km
jpds(5)=kp5(k)
jpds(6)=kp6(k)
jpds(7)=kp7(k)
j=0
call getgb(lug,lui,jf,j,jpds,jgds,kf,j,kpds(1,k),kgds(1,k),
& lb,f(1,k),iret)
if(iret.ne.0) call exit(1)
if(mod(kpds(4,k)/64,2).eq.1) call exit(2)
enddo
idrt=kgds(1,1)
imax=kgds(2,1)
jmax=kgds(3,1)
c
call sptruns(iromb,maxwv,idrt,imax,jmax,km,nps,
& 0,0,0,jf,0,0,0,0,true,xmesh,orient,f,gn,gs)
c
do k=1,km
kpds(3,k)=27
kgds(1,k)=5
kgds(2,k)=nps
kgds(3,k)=nps
kgds(4,k)=nint(rlatn1*1.e3)
kgds(5,k)=nint(rlonn1*1.e3)
kgds(6,k)=8
kgds(7,k)=nint(orient*1.e3)
kgds(8,k)=nint(xmesh)
kgds(9,k)=nint(xmesh)
kgds(10,k)=0
kgds(11,k)=64
call putgb(lun,npq,kpds(1,k),kgds(1,k),lb,gn(1,k),iret)
enddo
do k=1,km
kpds(3,k)=28
kgds(1,k)=5
kgds(2,k)=nps
kgds(3,k)=nps
kgds(4,k)=nint(rlats1*1.e3)
kgds(5,k)=nint(rlons1*1.e3)
kgds(6,k)=8
kgds(7,k)=nint(mod(orient+180,360.)*1.e3)
kgds(8,k)=nint(xmesh)
kgds(9,k)=nint(xmesh)
kgds(10,k)=128
kgds(11,k)=64
call putgb(lus,npq,kpds(1,k),kgds(1,k),lb,gs(1,k),iret)
enddo
c
end
c
subroutine gv65(lug,lui,lun,lus,jf,km,kp5,kp6,kp7,iromb,maxwv)
c interpolates a vector field using spectral transforms.
integer kp5(km),kp6(km),kp7(km)
c output grids are 65x65 (381 km true at latitide 60).
c nh grid oriented at 280E; sh grid oriented at 100E.
c winds are rotated to be relative to grid coordinates.
parameter(nph=32,nps=2*nph+1,npq=nps*nps)
parameter(true=60.,xmesh=381.e3,orient=280.)
parameter(rerth=6.3712e6)
parameter(pi=3.14159265358979,dpr=180./pi)
real un(npq,km),vn(npq,km),us(npq,km),vs(npq,km)
integer jpds(25),jgds(22),kpds(25,km),kgds(22,km)
logical lb(jf)
real u(jf,km),v(jf,km)
c
g2=((1.+sin(abs(true)/dpr))*rerth/xmesh)**2
r2=2*nph**2
rlatn1=dpr*asin((g2-r2)/(g2+r2))
rlonn1=mod(orient+315,360.)
rlats1=-rlatn1
rlons1=mod(rlonn1+270,360.)
jpds=-1
do k=1,km
jpds(5)=kp5(k)
jpds(6)=kp6(k)
jpds(7)=kp7(k)
j=0
call getgb(lug,lui,jf,j,jpds,jgds,kf,j,kpds(1,k),kgds(1,k),
& lb,u(1,k),iret)
if(iret.ne.0) call exit(1)
if(mod(kpds(4,k)/64,2).eq.1) call exit(2)
jpds=kpds(:,k)
jgds=kgds(:,k)
jpds(5)=jpds(5)+1
j=0
call getgb(lug,lui,jf,j,jpds,jgds,kf,j,kpds(1,k),kgds(1,k),
& lb,v(1,k),iret)
if(iret.ne.0) call exit(1)
if(mod(kpds(4,k)/64,2).eq.1) call exit(2)
enddo
idrt=kgds(1,1)
imax=kgds(2,1)
jmax=kgds(3,1)
c
call sptrunsv(iromb,maxwv,idrt,imax,jmax,km,nps,
& 0,0,0,jf,0,0,0,0,true,xmesh,orient,u,v,
& .true.,un,vn,us,vs,.false.,dum,dum,dum,dum,
& .false.,dum,dum,dum,dum)
c
do k=1,km
kpds(3,k)=27
kgds(1,k)=5
kgds(2,k)=nps
kgds(3,k)=nps
kgds(4,k)=nint(rlatn1*1.e3)
kgds(5,k)=nint(rlonn1*1.e3)
kgds(6,k)=8
kgds(7,k)=nint(orient*1.e3)
kgds(8,k)=nint(xmesh)
kgds(9,k)=nint(xmesh)
kgds(10,k)=0
kgds(11,k)=64
kpds(5,k)=kp5(k)
call putgb(lun,npq,kpds(1,k),kgds(1,k),lb,un(1,k),iret)
enddo
do k=1,km
kpds(3,k)=27
kgds(1,k)=5
kgds(2,k)=nps
kgds(3,k)=nps
kgds(4,k)=nint(rlatn1*1.e3)
kgds(5,k)=nint(rlonn1*1.e3)
kgds(6,k)=8
kgds(7,k)=nint(orient*1.e3)
kgds(8,k)=nint(xmesh)
kgds(9,k)=nint(xmesh)
kgds(10,k)=0
kgds(11,k)=64
kpds(5,k)=kp5(k)+1
call putgb(lun,npq,kpds(1,k),kgds(1,k),lb,vn(1,k),iret)
enddo
do k=1,km
kpds(3,k)=28
kgds(1,k)=5
kgds(2,k)=nps
kgds(3,k)=nps
kgds(4,k)=nint(rlats1*1.e3)
kgds(5,k)=nint(rlons1*1.e3)
kgds(6,k)=8
kgds(7,k)=nint(mod(orient+180,360.)*1.e3)
kgds(8,k)=nint(xmesh)
kgds(9,k)=nint(xmesh)
kgds(10,k)=128
kgds(11,k)=64
kpds(5,k)=kp5(k)
call putgb(lus,npq,kpds(1,k),kgds(1,k),lb,us(1,k),iret)
enddo
do k=1,km
kpds(3,k)=28
kgds(1,k)=5
kgds(2,k)=nps
kgds(3,k)=nps
kgds(4,k)=nint(rlats1*1.e3)
kgds(5,k)=nint(rlons1*1.e3)
kgds(6,k)=8
kgds(7,k)=nint(mod(orient+180,360.)*1.e3)
kgds(8,k)=nint(xmesh)
kgds(9,k)=nint(xmesh)
kgds(10,k)=128
kgds(11,k)=64
kpds(5,k)=kp5(k)+1
call putgb(lus,npq,kpds(1,k),kgds(1,k),lb,vs(1,k),iret)
enddo
c
end
Example 2. Spectrally truncate winds in place on a latlon grid.
c unit number 11 is the input latlon grib file
c unit number 31 is the input latlon grib index file
c unit number 51 is the output latlon grib file
c nominal spectral truncation is r40
c maximum input gridsize is 360x181
c maximum number of levels wanted is 12
parameter(lug=11,lui=31,luo=51)
parameter(iromb=1,maxwv=40,jf=360*181,kx=12)
integer kp5(kx),kp6(kx),kp7(kx)
integer kpo(kx)
data kpo/1000,850,700,500,400,300,250,200,150,100,70,50/
c winds
km=12
kp5=33
kp6=100
kp7=kpo
call gvr40(lug,lui,luo,jf,km,kp5,kp6,kp7,iromb,maxwv)
c
stop
end
c
subroutine gvr40(lug,lui,luo,jf,km,kp5,kp6,kp7,iromb,maxwv)
c interpolates a vector field using spectral transforms.
integer kp5(km),kp6(km),kp7(km)
integer jpds(25),jgds(22),kpds(25,km),kgds(22,km)
logical lb(jf)
real u(jf,km),v(jf,km)
c
jpds=-1
do k=1,km
jpds(5)=kp5(k)
jpds(6)=kp6(k)
jpds(7)=kp7(k)
j=0
call getgb(lug,lui,jf,j,jpds,jgds,kf,j,kpds(1,k),kgds(1,k),
& lb,u(1,k),iret)
if(iret.ne.0) call exit(1)
if(mod(kpds(4,k)/64,2).eq.1) call exit(2)
jpds=kpds(:,k)
jgds=kgds(:,k)
jpds(5)=jpds(5)+1
j=0
call getgb(lug,lui,jf,j,jpds,jgds,kf,j,kpds(1,k),kgds(1,k),
& lb,v(1,k),iret)
if(iret.ne.0) call exit(1)
if(mod(kpds(4,k)/64,2).eq.1) call exit(2)
enddo
idrt=kgds(1,1)
imax=kgds(2,1)
jmax=kgds(3,1)
c
call sptrunv(iromb,maxwv,idrt,imax,jmax,idrt,imax,jmax,km,
& 0,0,0,jf,0,0,jf,0,u,v,.true.,u,v,
& .false.,dum,dum,.false.,dum,dum)
c
do k=1,km
kpds(5,k)=kp5(k)
call putgb(luo,kf,kpds(1,k),kgds(1,k),lb,u(1,k),iret)
enddo
do k=1,km
kpds(5,k)=kp5(k)+1
call putgb(luo,kf,kpds(1,k),kgds(1,k),lb,v(1,k),iret)
enddo
c
end
Example 3. Compute latlon temperatures from spectral temperatures and
compute latlon winds from spectral divergence and vorticity.
c unit number 11 is the input sigma file
c unit number 51 is the output latlon file
c nominal spectral truncation is t62
c output gridsize is 144x73
c number of levels is 28
parameter(iromb=0,maxwv=62)
parameter(idrt=0,im=144,jm=73)
parameter(levs=28)
parameter(mx=(maxwv+1)*((iromb+1)*maxwv+2)/2)
real t(mx,levs),d(mx,levs),z(mx,levs)
real tg(im,jm,km),ug(im,jm,km),vg(im,jm,km)
c temperature
do k=1,4
read(11)
enddo
do k=1,levs
read(11) (t(m,k),m=1,mx)
enddo
call sptran(iromb,maxwv,idrt,im,jm,levs,0,0,0,0,0,0,0,0,1,
& t,tg(1,1,1),tg(1,jm,1),1)
call sptran(
do k=1,levs
write(51) ((tg(i,j,k),i=1,im),j=1,jm)
enddo
c winds
do k=1,levs
read(11) (d(m,k),m=1,mx)
read(11) (z(m,k),m=1,mx)
enddo
call sptranv(iromb,maxwv,idrt,im,jm,levs,0,0,0,0,0,0,0,0,1,
& d,z,ug(1,1,1),ug(1,jm,1),vg(1,1,1),vg(1,jm,1),1)
do k=1,levs
write(51) ((ug(i,j,k),i=1,im),j=1,jm)
write(51) ((vg(i,j,k),i=1,im),j=1,jm)
enddo
end