NCEPLIBS-g2  3.5.0
g2spec.F90
Go to the documentation of this file.
1 
7 
24 subroutine specpack(fld,ndpts,JJ,KK,MM,idrstmpl,cpack,lcpack)
25 
26  real,intent(in) :: fld(ndpts)
27  integer,intent(in) :: ndpts,JJ,KK,MM
28  integer,intent(inout) :: idrstmpl(*)
29  character(len=1),intent(out) :: cpack(*)
30  integer,intent(out) :: lcpack
31 
32  integer :: Ts,tmplsim(5)
33  real :: bscale,dscale,unpk(ndpts),tfld(ndpts)
34  real,allocatable :: pscale(:)
35 
36  bscale = 2.0**real(-idrstmpl(2))
37  dscale = 10.0**real(idrstmpl(3))
38  nbits = idrstmpl(4)
39  js=idrstmpl(6)
40  ks=idrstmpl(7)
41  ms=idrstmpl(8)
42  ts=idrstmpl(9)
43 
44  ! Calculate Laplacian scaling factors for each possible wave number.
45  allocate(pscale(jj+mm))
46  tscale=real(idrstmpl(5))*1e-6
47  do n=js,jj+mm
48  pscale(n)=real(n*(n+1))**(tscale)
49  enddo
50 
51  ! Separate spectral coeffs into two lists; one to contain unpacked
52  ! values within the sub-spectrum Js, Ks, Ms, and the other with
53  ! values outside of the sub-spectrum to be packed.
54  inc=1
55  incu=1
56  incp=1
57  do m=0,mm
58  nm=jj ! triangular or trapezoidal
59  if (kk .eq. jj+mm) nm=jj+m ! rhombodial
60  ns=js ! triangular or trapezoidal
61  if (ks .eq. js+ms) ns=js+m ! rhombodial
62  do n=m,nm
63  if (n.le.ns .AND. m.le.ms) then ! save unpacked value
64  unpk(incu)=fld(inc) ! real part
65  unpk(incu+1)=fld(inc+1) ! imaginary part
66  inc=inc+2
67  incu=incu+2
68  else
69  ! Save value to be packed and scale Laplacian scale factor.
70  tfld(incp)=fld(inc)*pscale(n) ! real part
71  tfld(incp+1)=fld(inc+1)*pscale(n) ! imaginary part
72  inc=inc+2
73  incp=incp+2
74  endif
75  enddo
76  enddo
77 
78  deallocate(pscale)
79 
80  incu=incu-1
81  if (incu .ne. ts) then
82  print *,'specpack: Incorrect number of unpacked values ', 'given:',ts
83  print *,'specpack: Resetting idrstmpl(9) to ',incu
84  ts=incu
85  endif
86 
87  ! Add unpacked values to the packed data array in 32-bit IEEE format.
88  call mkieee(unpk,cpack,ts)
89  ipos=4*ts
90 
91  ! Scale and pack the rest of the coefficients.
92  tmplsim(2)=idrstmpl(2)
93  tmplsim(3)=idrstmpl(3)
94  tmplsim(4)=idrstmpl(4)
95  call simpack(tfld,ndpts-ts,tmplsim,cpack(ipos+1),lcpack)
96  lcpack=lcpack+ipos
97 
98  ! Fill in Template 5.51.
99  idrstmpl(1)=tmplsim(1)
100  idrstmpl(2)=tmplsim(2)
101  idrstmpl(3)=tmplsim(3)
102  idrstmpl(4)=tmplsim(4)
103  idrstmpl(9)=ts
104  idrstmpl(10)=1 ! Unpacked spectral data is 32-bit IEEE
105 
106 end subroutine specpack
107 
123 subroutine specunpack(cpack, len, idrstmpl, ndpts, JJ, KK, MM, fld)
124 
125  character(len = 1), intent(in) :: cpack(len)
126  integer, intent(in) :: ndpts, len, JJ, KK, MM
127  integer, intent(in) :: idrstmpl(*)
128  real, intent(out) :: fld(ndpts)
129 
130  integer :: ifld(ndpts), Ts
131  integer(4) :: ieee
132  real :: ref, bscale, dscale, unpk(ndpts)
133  real, allocatable :: pscale(:)
134 
135  ieee = idrstmpl(1)
136  call rdieee(ieee, ref, 1)
137  bscale = 2.0**real(idrstmpl(2))
138  dscale = 10.0**real(-idrstmpl(3))
139  nbits = idrstmpl(4)
140  js = idrstmpl(6)
141  ks = idrstmpl(7)
142  ms = idrstmpl(8)
143  ts = idrstmpl(9)
144 
145  if (idrstmpl(10) .eq. 1) then ! unpacked floats are 32-bit IEEE
146  call rdieeec(cpack, unpk, ts) ! read IEEE unpacked floats
147  iofst = 32 * ts
148  call g2_gbytesc(cpack, ifld, iofst, nbits, 0, ndpts - ts) ! unpack scaled data
149 
150  ! Calculate Laplacian scaling factors for each possible wave number.
151  allocate(pscale(jj + mm))
152  tscale = real(idrstmpl(5)) * 1e-6
153  do n = js, jj + mm
154  pscale(n) = real(n * (n + 1))**(-tscale)
155  enddo
156 
157  ! Assemble spectral coeffs back to original order.
158  inc = 1
159  incu = 1
160  incp = 1
161  do m = 0, mm
162  nm = jj ! triangular or trapezoidal
163  if (kk .eq. jj + mm) nm = jj + m ! rhombodial
164  ns = js ! triangular or trapezoidal
165  if (ks .eq. js + ms) ns = js + m ! rhombodial
166  do n = m, nm
167  if (n .le. ns .AND. m .le. ms) then ! grab unpacked value
168  fld(inc) = unpk(incu) ! real part
169  fld(inc + 1) = unpk(incu + 1) ! imaginary part
170  inc = inc + 2
171  incu = incu + 2
172  else ! Calc coeff from packed value
173  fld(inc) = ((real(ifld(incp))*bscale) + ref)*dscale*pscale(n) ! real part
174  fld(inc + 1) = ((real(ifld(incp + 1)) * bscale) + ref) * dscale * pscale(n) ! imaginary part
175  inc = inc + 2
176  incp = incp + 2
177  endif
178  enddo
179  enddo
180  deallocate(pscale)
181  else
182  print *, 'specunpack: Cannot handle 64 or 128-bit floats.'
183  fld = 0.0
184  endif
185 end subroutine specunpack
subroutine g2_gbytesc(in, iout, iskip, nbits, nskip, n)
Extract arbitrary size big-endian integer values (up to 32 bits each) from a packed bit string.
Definition: g2bytes.F90:120
subroutine rdieee(rieee, a, num)
Copy array of 32-bit IEEE floating point values to local floating point representation.
Definition: g2bytes.F90:637
subroutine mkieee(a, rieee, num)
Copy an array of real to an array of 32-bit IEEE floating points.
Definition: g2bytes.F90:685
subroutine rdieeec(cieee, a, num)
Copy array of 32-bit IEEE floating point values stored in char array to local floating point represen...
Definition: g2bytes.F90:607
subroutine simpack(fld, ndpts, idrstmpl, cpack, lcpack)
Pack a data field using a simple packing algorithm.
Definition: g2sim.F90:27
subroutine specpack(fld, ndpts, JJ, KK, MM, idrstmpl, cpack, lcpack)
Pack a spectral data field using the complex packing algorithm for spherical harmonic data as defined...
Definition: g2spec.F90:25
subroutine specunpack(cpack, len, idrstmpl, ndpts, JJ, KK, MM, fld)
Unpack a spectral data field using the complex packing algorithm for spherical harmonic data,...
Definition: g2spec.F90:124