subroutine w3fi72(itype,fld,ifld,ibitl, & ipflag,id,pds, & igflag,igrid,igds,icomp, & ibflag,ibmap,iblen,ibdsfl, & npts,kbuf,itot,jerr) c$$$ subprogram documentation block c . . . . c subprogram: w3fi72 make a complete grib message c prgmmr: farley org: nmc421 date:94-11-22 c c abstract: makes a complete grib message from a user supplied c array of floating point or integer data. the user has the c option of supplying the pds or an integer array that will be c used to create a pds (with w3fi68). the user must also c supply other necessary info; see usage section below. c c program history log: c 91-05-08 r.e.jones c 92-07-01 m. farley added gds and bms logic. placed existing c logic for bds in a routine. c 92-10-02 r.e.jones add error exit for w3fi73 c 93-04-30 r.e.jones replace do loops to move character data c with xmovex, use xstore to zero character c array. make change so flat field will pack. c 93-08-06 cavanaugh modified call to w3fi75 c 93-10-26 cavanaugh added code to restore input field to original c values if d-scale not 0 c 94-01-27 cavanaugh added igds array in call to w3fi75 to provide c information for boustrophedonic processing c 94-03-03 cavanaugh increased size of gds array for thin grids c 94-05-16 farley cleaned up documentation c 94-11-10 farley increased size of pfld/ifld arrarys from c 100k to 260k for .5 degree sst anal fields c 94-12-04 r.e.jones change document for ipflag. c 95-10-31 iredell removed saves and prints c 98-05-19 gilbert increased array dimensions to handle grids c of up to 500,000 grid points. c 95-10-31 iredell generalized word size c 98-12-21 gilbert replaced function ichar with mova2i. c 99-02-01 gilbert changed the method of zeroing out array kbuf. c the old method, using w3fi01 and xstore was c incorrect with 4-byte integers and 8-byte reals. c c usage: call w3fi72(itype,fld,ifld,ibitl, c & ipflag,id,pds, c & igflag,igrid,igds,icomp, c & ibflag,ibmap,iblen,ibdsfl, c & ibdsfl, c & npts,kbuf,itot,jerr) c c input argument list: c itype - 0 = floating point data supplied in array 'fld' c 1 = integer data supplied in array 'ifld' c fld - real array of data (at proper gridpoints) to be c converted to grib format if itype=0. c see remarks #1 & 2. c ifld - integer array of data (at proper gridpoints) to be c converted to grib format if itype=1. c see remarks #1 & 2. c ibitl - 0 = computer computes length for packing data from c power of 2 (number of bits) best fit of data c using 'variable' bit packer w3fi58. c 8, 12, etc. computer rescales data to fit into that c 'fixed' number of bits using w3fi59. c see remarks #3. c c ipflag - 0 = make pds from user supplied array (id) c 1 = user supplying pds c note: if pds is greater than 30, use iplfag=1. c the user could call w3fi68 before he calls c w3fi72. this would make the first 30 bytes of c the pds, user then would make bytes after 30. c id - integer array of values that w3fi68 will use c to make an edition 1 pds if ipflag=0. (see the c docblock for w3fi68 for layout of array) c pds - character array of values (valid pds supplied c by user) if ipflag=1. length may exceed 28 bytes c (contents of bytes beyond 28 are passed c through unchanged). c c igflag - 0 = make gds based on 'igrid' value. c 1 = make gds from user supplied info in 'igds' c and 'igrid' value. c see remarks #4. c igrid - # = grid identification (table b) c 255 = if user defined grid; igds must be supplied c and igflag must =1. c igds - integer array containing user gds info (same c format as supplied by w3fi71 - see dockblock for c layout) if igflag=1. c icomp - resolution and component flag for bit 5 of gds(17) c 0 = earth oriented winds c 1 = grid oriented winds c c ibflag - 0 = make bit map from user supplied data c # = bit map predefined by center c see remarks #5. c ibmap - integer array containing bit map c iblen - length of bit map will be used to verify length c of field (error if it doesn't match). c c ibdsfl - integer array containing table 11 flag info c bds octet 4: c (1) 0 = grid point data c 1 = spherical harmonic coefficients c (2) 0 = simple packing c 1 = second order packing c (3) ... same value as 'itype' c 0 = original data were floating point values c 1 = original data were integer values c (4) 0 = no additional flags at octet 14 c 1 = octet 14 contains flag bits 5-12 c (5) 0 = reserved - always set to 0 c byte 6 option 1 not available (as of 5-16-93) c (6) 0 = single datum at each grid point c 1 = matrix of values at each grid point c byte 7 option 0 with second order packing n/a (as of 5-16-93) c (7) 0 = no secondary bit maps c 1 = secondary bit maps present c (8) 0 = second order values have constant width c 1 = second order values have different widths c c output argument list: c npts - number of gridpoints in array fld or ifld c kbuf - entire grib message ('grib' to '7777') c equivalence to integer array to make sure it c is on word bounary. c itot - total length of grib message in bytes c jerr - = 0, completed making grib field without error c 1, ipflag not 0 or 1 c 2, igflag not 0 or 1 c 3, error converting ieee f.p. number to ibm370 f.p. c 4, w3fi71 error/igrid not defined c 5, w3fk74 error/grid representation type not valid c 6, grid too large for packer dimension arrays c see automation division for revision! c 7, length of bit map not equal to size of fld/ifld c 8, w3fi73 error, all values in ibmap are zero c c output files: c ft06f001 - standard fortran output print file c c subprograms called: c library: c w3lib - w3fi58, w3fi59, w3fi68, w3fi71, w3fi73, w3fi74 c w3fi75, w3fi76 c fortran 90 intrinsic - bit_size c c remarks: c 1) if bit map to be included in message, null data should c be included in fld or ifld. this routine will take care c of 'discarding' any null data based on the bit map. c 2) units must be those in grib documentation: nmc o.n. 388 c or wmo publication 306. c 3) in either case, input numbers will be multiplied by c '10 to the nth' power found in id(25) or pds(27-28), c the d-scaling factor, prior to binary packing. c 4) all nmc produced grib fields will have a grid definition c section included in the grib message. id(6) will be c set to '1'. c - gds will be built based on grid number (igrid), unless c igflag=1 (user supplying igds). user must still supply c igrid even if igds provided. c 5) if bit map used then id(7) or pds(8) must indicate the c presence of a bit map. c 6) array kbuf should be equivalenced to an integer value or c array to make sure it is on a word boundary. c 7) subprogram can be called from a multiprocessing environment. c c attributes: c language: fortran 90 c c$$$ c real fld(*) c integer ibdsfl(*) integer ibmap(*) integer id(*) integer ifld(*) integer igds(*) integer,allocatable:: ipfld(:) integer ib(4) c character * 1 bds11(11) character * 1 kbuf(*) character * 1 pds(*) character * 1 gds(200) character(1),allocatable:: bms(:) character(1),allocatable:: pfld(:) character * 1 seven character * 1 zero c c c ascii rep of /'G', 'R', 'I', 'B'/ c data ib / 71, 82, 73, 66/ c ier = 0 iberr = 0 jerr = 0 igribl = 8 ipdsl = 0 lengds = 0 lenbms = 0 lenbds = 0 itoss = 0 c c$ 1.0 product definition section(pds). c c set id(6) to 1 ...or... modify pds(8) ... c regardless of user specification... c nmc grib fields will always have a gds c if (ipflag .eq.0) then id(6) = 1 call w3fi68(id,pds) else if (ipflag .eq. 1) then if (iand(mova2i(pds(8)),64) .eq. 64) then c both gds and bms pds(8) = char(192) else if (mova2i(pds(8)) .eq. 0) then c gds only pds(8) = char(128) end if continue else c print *,' w3fi72 error, ipflag is not 0 or 1 ipflag = ',ipflag jerr = 1 go to 900 end if c c get length of pds c ipdsl = mova2i(pds(1)) * 65536 + mova2i(pds(2)) * 256 + & mova2i(pds(3)) c c$ 2.0 grid definition section (gds). c c if igflag=1 then user is supplying the igds information c if (igflag .eq. 0) then call w3fi71(igrid,igds,igerr) if (igerr .eq. 1) then c print *,' w3fi71 error, grid type not defined...',igrid jerr = 4 go to 900 end if end if if (igflag .eq. 0 .or. igflag .eq.1) then call w3fi74(igds,icomp,gds,lengds,npts,igerr) if (igerr .eq. 1) then c print *,' w3fi74 error, grid rep type not valid...',igds(3) jerr = 5 go to 900 else end if else c print *,' w3fi72 error, igflag is not 0 or 1 igflag = ',igflag jerr = 2 go to 900 end if c c$ 3.0 bit map section (bms). c c set itoss=1 if bitmap being used. w3fi75 will toss data c prior to packing. later coding will be needed when the c 'predefined' grids are finally 'defined'. c if (mova2i(pds(8)) .eq. 64 .or. & mova2i(pds(8)) .eq. 192) then itoss = 1 if (ibflag .eq. 0) then if (iblen .ne. npts) then c print *,' w3fi72 error, iblen .ne. npts = ',iblen,npts jerr = 7 go to 900 end if allocate(bms(npts/8+6)) call w3fi73(ibflag,ibmap,iblen,bms,lenbms,ier) if (ier .ne. 0) then c print *,' w3fi73 error, ibmap values are all zero' jerr = 8 go to 900 end if else c print *,' bit map predefined by center, ibflag = ',ibflag end if end if c c$ 4.0 binary data section (bds). c c$ 4.1 scale the data with d-scale from pds(27-28) c jscale = mova2i(pds(27)) * 256 + mova2i(pds(28)) if (iand(jscale,32768).ne.0) then jscale = - iand(jscale,32767) end if scale = 10.0 ** jscale if (itype .eq. 0) then do 410 i = 1,npts fld(i) = fld(i) * scale 410 continue else do 411 i = 1,npts ifld(i) = nint(float(ifld(i)) * scale) 411 continue end if c c$ 4.2 call w3fi75 to pack data and make bds. c allocate(pfld(npts*4)) c if(ibdsfl(2).ne.0) then allocate(ipfld(npts*32/bit_size(1)+1)) ipfld=0 endif c call w3fi75(ibitl,itype,itoss,fld,ifld,ibmap,ibdsfl, & npts,bds11,ipfld,pfld,len,lenbds,iberr,pds,igds) c if(ibdsfl(2).ne.0) then call xmovex(pfld,ipfld,npts*4) deallocate(ipfld) endif c if (iberr .eq. 1) then jerr = 3 go to 900 end if c 4.3 if d-scale not 0, rescale input field to c original value c if (jscale.ne.0) then dscale = 1.0 / scale if (itype.eq.0) then do 412 i = 1, npts fld(i) = fld(i) * dscale 412 continue else do 413 i = 1, npts fld(i) = nint(float(ifld(i)) * dscale) 413 continue end if end if c c$ 5.0 output section. c c$ 5.1 zero out the output array kbuf. c zero = char(00) itot = igribl + ipdsl + lengds + lenbms + lenbds + 4 c print *,'igribl =',igribl c print *,'ipdsl =',ipdsl c print *,'lengds =',lengds c print *,'lenbms =',lenbms c print *,'lenbds =',lenbds c print *,'itot =',itot kbuf(1:itot)=zero c c$ 5.2 move section 0 - 'is' into kbuf (8 bytes). c istart = 0 do 520 i = 1,4 kbuf(i) = char(ib(i)) 520 continue c kbuf(5) = char(mod(itot / 65536,256)) kbuf(6) = char(mod(itot / 256,256)) kbuf(7) = char(mod(itot ,256)) kbuf(8) = char(1) c c$ 5.3 move section 1 - 'pds' into kbuf (28 bytes). c istart = istart + igribl if (ipdsl.gt.0) then call xmovex(kbuf(istart+1),pds,ipdsl) else c print *,'length of pds less or equal 0, ipdsl = ',ipdsl end if c c$ 5.4 move section 2 - 'gds' into kbuf. c istart = istart + ipdsl if (lengds .gt. 0) then call xmovex(kbuf(istart+1),gds,lengds) end if c c$ 5.5 move section 3 - 'bms' into kbuf. c istart = istart + lengds if (lenbms .gt. 0) then call xmovex(kbuf(istart+1),bms,lenbms) end if c c$ 5.6 move section 4 - 'bds' into kbuf. c c$ move the first 11 octets of the bds into kbuf. c istart = istart + lenbms call xmovex(kbuf(istart+1),bds11,11) c c$ move the packed data into the kbuf c istart = istart + 11 if (len.gt.0) then call xmovex(kbuf(istart+1),pfld,len) end if c c$ add '7777' to end off kbuf c note that these 4 octets not included in actual size of bds. c seven = char(55) istart = itot - 4 do 562 i = 1,4 kbuf(istart+i) = seven 562 continue c 900 continue if(allocated(bms)) deallocate(bms) if(allocated(pfld)) deallocate(pfld) return end