WAVEWATCH III  beta 0.0.1
ww3_bounc.F90
Go to the documentation of this file.
1 
7 !
8 
9 #include "w3macros.h"
10 !/ ------------------------------------------------------------------- /
21 !
22 PROGRAM w3bounc
23  !/
24  !/ +-----------------------------------+
25  !/ | WAVEWATCH III NOAA/NCEP |
26  !/ | F. Ardhuin |
27  !/ | M. Accensi |
28  !/ | FORTRAN 90 |
29  !/ | Last update : 21-Jul-2020 |
30  !/ +-----------------------------------+
31  !/
32  !/ 24-May-2013 : Adaptation from ww3_bound.ftn ( version 4.08 )
33  !/ 1-Apr-2015 : Add checks on lat lon xfr ( version 5.05 )
34  !/ 11-May-2015 : Allow use of cartesian grids ( version 5.08 )
35  !/ 17-Aug-2016 : Bug correction on RDBPO ( version 5.10 )
36  !/ 20-Oct-2016 : Error statement updates ( version 5.15 )
37  !/ 20-Mar-2018 : Improve netcdf file reading ( version 6.02 )
38  !/ 15-May-2018 : Add namelist feature ( version 6.05 )
39  !/ 04-May-2020 : Update spectral conversion ( version 7.11 )
40  !/ 21-Jul-2020 : Support rotated pole grid ( version 7.11 )
41  !/
42  !/
43  !/ Copyright 2012-2013 National Weather Service (NWS),
44  !/ National Oceanic and Atmospheric Administration. All rights
45  !/ reserved. WAVEWATCH III is a trademark of the NWS.
46  !/ No unauthorized use without permission.
47  !/
48  ! 1. Purpose :
49  !
50  ! Combines spectra files into a nest.ww3 file for boundary conditions
51  !
52  ! 2. Method :
53  !
54  ! Finds nearest points and performs linear interpolation
55  !
56  ! The initial conditions are written to the restart.ww3 using the
57  ! subroutine W3IORS. Note that the name of the restart file is set
58  ! in W3IORS.
59  !
60  ! 3. Parameters :
61  !
62  ! Local parameters.
63  ! ----------------------------------------------------------------
64  ! NDSI Int. Input unit number ("ww3_assm.inp").
65  ! ITYPE Int. Type of data
66  ! ----------------------------------------------------------------
67  !
68  ! 4. Subroutines used :
69  !
70  ! Name Type Module Description
71  ! ----------------------------------------------------------------
72  ! STRACE Subr. Id. Subroutine tracing.
73  ! NEXTLN Subr. Id. Get next line from input filw
74  ! EXTCDE Subr. Id. Abort program as graceful as possible.
75  ! WAVNU1 Subr. W3DISPMD Solve dispersion relation.
76  ! W3IOGR Subr. W3IOGRMD Reading/writing model definition file.
77  ! W3EQTOLL Subr W3SERVMD Convert coordinates from rotated pole.
78  ! ----------------------------------------------------------------
79  !
80  ! 5. Called by :
81  !
82  ! None, stand-alone program.
83  !
84  ! 6. Error messages :
85  !
86  ! 7. Remarks :
87  !
88  ! - Can be used also to diagnose contents of nest.ww3 file
89  ! in read mode
90  !
91  ! - Input spectra are assumed to be formulated on a standard
92  ! pole. However, the model grid can be on a rotated pole.
93  !
94  ! 8. Structure :
95  !
96  ! ----------------------------------------------------
97  ! 1.a Set up data structures.
98  ! ( W3NMOD , W3NDAT , W3NOUT
99  ! W3SETG , W3SETW , W3SETO )
100  ! b I-O setup.
101  ! ....
102  ! 9. Convert energy to action
103  ! 10. Write restart file. ( W3IORS )
104  ! ----------------------------------------------------
105  !
106  ! 9. Switches :
107  !
108  ! !/SHRD Switch for shared / distributed memory architecture.
109  ! !/DIST Id.
110  !
111  ! !/SHRD Switch for message passing method.
112  ! !/MPI Id.
113  !
114  ! !/S Enable subroutine tracing.
115  !
116  ! !/O4 Output normalized 1-D energy spectrum.
117  ! !/O5 Output normalized 2-D energy spectrum.
118  ! !/O6 Output normalized wave heights (not MPP adapted).
119  !
120  ! 10. Source code :
121  !
122  !/ ------------------------------------------------------------------- /
123  USE constants
124  USE w3wdatmd, ONLY: w3ndat, w3setw
125  USE w3adatmd, ONLY: w3naux, w3seta
126  USE w3odatmd, ONLY: w3nout, w3seto, fnmpre, ndst, ndse
127  USE w3cspcmd, ONLY: w3cspc
128 
129 
130  USE w3gdatmd, ONLY: nk, nth, xfr, fr1, dth, th, fachfe, &
131  gname, w3nmod, w3setg,&
132  nsea, mapsta, gtype, xgrd, ygrd, x0, y0, &
134 #ifdef W3_RTD
135  USE w3gdatmd, ONLY : polat, polon
136 #endif
137  USE w3odatmd, ONLY: ndso, ndse
138  USE w3iobcmd, ONLY: verbptbc, idstrbc
139  USE w3iogrmd, ONLY: w3iogr
140  USE w3timemd
141  USE w3servmd, ONLY: itrace, nextln, extcde, dist_sphere
142 #ifdef W3_RTD
143  USE w3servmd, ONLY: w3eqtoll
144 #endif
145  USE w3nmlbouncmd
146  USE netcdf
147 #ifdef W3_S
148  USE w3servmd, ONLY : strace
149 #endif
150 
151  !/
152  IMPLICIT NONE
153  !
154 #ifdef W3_MPI
155  include "mpif.h"
156 #endif
157  !/
158  !/ ------------------------------------------------------------------- /
159  !/ Local parameters
160  !/
161 
162  TYPE(nml_bound_t) :: nml_bound
163  !
164  INTEGER :: ix, iy, isea, i,jj,ip,ip1,j,it, &
165  ndsi,ndsm, ndsi2,ndss,ndsb, ndsc, &
166  ndstrc, ntrace, nk1,nth1,nt1, nspec1, &
167  nbi, nbi2, nki, nthi, nti, nbo, nbo2, &
168  ierr, interp, iloop, verbose, ibo, &
169  iret, icode, ndsl
170  INTEGER :: time(2), time2(2), varid(12), &
171  refdate(8), curdate(8), vartype
172 #ifdef W3_S
173  INTEGER, SAVE :: ient = 0
174 #endif
175  !
176  INTEGER, ALLOCATABLE :: ipbpi(:,:), ipbpo(:,:), ncid(:), &
177  dimid(:,:), dimln(:,:)
178  !
179  REAL :: fr1i, xfri, th1i, factor, offset, dmin,&
180  dist, dmin2, cos1, dlon, dlat, dlo, &
181  fillval
182  !
183  REAL, ALLOCATABLE :: spec2d(:,:,:,:), lats(:), lons(:), &
184  freq(:), theta(:), &
185  xbpi(:), ybpi(:), rdbpi(:,:), &
186  xbpo(:), ybpo(:), rdbpo(:,:), &
187  abpin(:,:), abpin2(:,:,:)
188 #ifdef W3_RTD
189  REAL, ALLOCATABLE :: xtmp(:), ytmp(:), angtmp(:)
190  LOGICAL :: isrtd
191 #endif
192  !
193  REAL, ALLOCATABLE :: tmpspci(:,:),tmpspco(:,:)
194 
195  !
196  DOUBLE PRECISION :: refjulday, curjulday
197  DOUBLE PRECISION, ALLOCATABLE :: times(:)
198  !
199  CHARACTER :: comstr*1, line*512, filename*512, &
200  inxout*5, file*128
201  CHARACTER*50 :: timeunits, calendar
202  CHARACTER*10 :: vertest ! = '2018-03-01'
203  CHARACTER*32 :: idtst != 'WAVEWATCH III BOUNDARY DATA FILE'
204  CHARACTER*512, ALLOCATABLE :: specfiles(:)
205  CHARACTER, ALLOCATABLE :: station(:,:)
206  !
207  LOGICAL :: flgnml, spconv
208  !
209  !/
210  !/ ------------------------------------------------------------------- /
211 
212 
213  !/
214  ! 1. IO set-up.
215  !
216  CALL w3nmod ( 1, 6, 6 )
217  CALL w3setg ( 1, 6, 6 )
218  CALL w3ndat ( 6, 6 )
219  CALL w3setw ( 1, 6, 6 )
220  CALL w3naux ( 6, 6 )
221  CALL w3seta ( 1, 6, 6 )
222  CALL w3nout ( 6, 6 )
223  CALL w3seto ( 1, 6, 6 )
224  !
225  ndsi = 10
226  ndsb = 33
227  ndsc = 44
228  ndsm = 20
229  ndss = 30
230  ndsl = 50
231  ndso = 6
232  ndse = 6
233  !
234  ndstrc = 6
235  ntrace = 10
236  CALL itrace ( ndstrc, ntrace )
237  !
238 #ifdef W3_S
239  CALL strace (ient, 'W3BOUNC')
240 #endif
241  !
242  WRITE (ndso,900)
243  !
244 
245  !
246  !--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
247  ! 2. Read model definition file.
248  !
249  CALL w3iogr ( 'READ', ndsm )
250  WRITE (ndso,920) gname
251 #ifdef W3_RTD
252  !
253  isrtd = polat .LT. 90.0
254  !
255 #endif
256  !
257  !--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
258  ! 3. Read requests from input file.
259  !
260 
261  !
262  ! process ww3_bounc namelist
263  !
264  INQUIRE(file=trim(fnmpre)//"ww3_bounc.nml", exist=flgnml)
265  IF (flgnml) THEN
266  ! Read namelist
267  CALL w3nmlbounc (ndsi, trim(fnmpre)//'ww3_bounc.nml', nml_bound, ierr)
268 
269  inxout = nml_bound%MODE
270  interp = nml_bound%INTERP
271  verbose = nml_bound%VERBOSE
272  file = nml_bound%FILE
273 
274  nbo2 = 0
275  OPEN(ndsl,file=trim(file),status='OLD',err=809,iostat=ierr)
276  rewind(ndsl)
277  DO
278  READ (ndsl,*,END=400,ERR=802)
279  nbo2 = nbo2 + 1
280  END DO
281 400 CONTINUE
282  ALLOCATE(specfiles(nbo2))
283  rewind(ndsl)
284  DO i=1,nbo2
285  READ (ndsl,'(A512)',END=801,ERR=802) SPECFILES(I)
286  END DO
287  CLOSE(ndsl)
288 
289  END IF ! FLGNML
290 
291  !
292  ! process old ww3_bounc.inp format
293  !
294  IF (.NOT. flgnml) THEN
295  OPEN (ndsi,file=trim(fnmpre)//'ww3_bounc.inp',status='OLD',err=805,iostat=ierr)
296  rewind(ndsi)
297 
298  READ (ndsi,'(A)',END=801,ERR=802,IOSTAT=IERR) comstr
299  IF (comstr.EQ.' ') comstr = '$'
300  WRITE (ndso,901) comstr
301 
302  CALL nextln ( comstr , ndsi , ndse )
303  READ (ndsi,*,END=801,ERR=802) inxout
304  CALL nextln ( comstr , ndsi , ndse )
305  READ (ndsi,*,END=801,ERR=802) interp
306  CALL nextln ( comstr , ndsi , ndse )
307  READ (ndsi,*,END=801,ERR=802) verbose
308  CALL nextln ( comstr , ndsi , ndse )
309  !
310  nbo2 = 0
311  !
312  ! ILOOP = 1 to count NBO2
313  ! ILOOP = 2 to read the file names
314  !
315  DO iloop = 1, 2
316  OPEN (ndss,file='ww3_bounc.scratch',form='FORMATTED', &
317  status='UNKNOWN')
318  IF ( iloop .EQ. 1 ) THEN
319  ndsi2 = ndsi
320  ELSE
321  ndsi2 = ndss
322  ALLOCATE(specfiles(nbo2))
323  nbo2=0
324  ENDIF
325 
326  nbo2=0
327  ! Read input file names
328  DO
329  CALL nextln ( comstr , ndsi2 , ndse )
330  READ (ndsi2,'(A512)') filename
331  jj = len_trim(filename)
332  IF ( iloop .EQ. 1 ) THEN
333  backspace(ndsi)
334  READ (ndsi,'(A)') line
335  WRITE (ndss,'(A)') line
336  END IF
337  IF (filename(:jj).EQ."'STOPSTRING'") EXIT
338  nbo2=nbo2+1
339  IF (iloop.EQ.1) cycle
340  specfiles(nbo2)=filename
341  END DO
342  !
343  IF ( iloop .EQ. 1 ) CLOSE ( ndss)
344  !
345  IF ( iloop .EQ. 2 ) CLOSE ( ndss, status='DELETE' )
346  END DO ! ILOOP = 1, 2
347  CLOSE(ndsi)
348 
349  END IF ! .NOT. FLGNML
350 
351 
352 
353  !
354  !--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
355  ! 4. Tests the reading of the file
356  !
357  IF ( inxout.EQ.'READ') THEN
358  OPEN(ndsb,file='nest.ww3',form='UNFORMATTED', convert=file_endian,status='old')
359  READ(ndsb) idtst, vertest, nk1, nth1, xfr, fr1i, th1i, nbi
360  nspec1 = nk1 * nth1
361  IF ( idtst .NE. idstrbc ) GOTO 803
362  WRITE(ndso,940) vertest
363  WRITE(ndso,941) idtst
364  IF (verbose.EQ.1) WRITE(ndso,'(A,2I5,3F12.6,I5)') 'NK,NTH,XFR, FR1I, TH1I, NBI :', &
365  nk1,nth1,xfr, fr1i, th1i, nbi
366  ALLOCATE (xbpi(nbi),ybpi(nbi))
367  ALLOCATE (ipbpi(nbi,4),rdbpi(nbi,4))
368  READ(ndsb) (xbpi(i),i=1,nbi), &
369  (ybpi(i),i=1,nbi), &
370  ((ipbpi(i,j),i=1,nbi),j=1,4), &
371  ((rdbpi(i,j),i=1,nbi),j=1,4)
372  IF (verbose.GE.1) WRITE(ndso,*) 'XBPI:',xbpi
373  IF (verbose.GE.1) WRITE(ndso,*) 'YBPI:',ybpi
374  IF (verbose.GE.1) WRITE(ndso,*) 'IPBPI:'
375  DO i=1,nbi
376  IF (verbose.GE.1) WRITE(ndso,*) i,' interpolated from:',ipbpi(i,1:4)
377  IF (verbose.GE.1) WRITE(ndso,*) i,' with coefficient :',rdbpi(i,1:4)
378  END DO
379  !
380  READ (ndsb) time2, nbi2
381  backspace(ndsb)
382  ALLOCATE (abpin(nspec1,nbi2))
383  ierr=0
384  DO WHILE (ierr.EQ.0)
385  READ (ndsb,iostat=ierr) time2, nbi2
386  IF (ierr.EQ.0) THEN
387  IF (verbose.EQ.1) WRITE(ndso,*) 'TIME2,NBI2:',time2, nbi2,ierr
388  DO ip=1, nbi2
389  READ (ndsb,END=803,ERR=804) ABPIN(:,IP)
390  END DO
391  END IF
392  END DO
393  CLOSE(ndsb)
394  END IF ! INXOUT.EQ.'READ'
395  !
396  !
397  IF ( inxout.EQ.'WRITE') THEN
398  !
399  !--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
400  ! 5. Defines position of active boundary points
401  !
402  nbo = 0
403  DO isea=1,nsea
404  ix = mapsf(isea,1)
405  iy = mapsf(isea,2)
406  IF (mapsta(iy,ix).EQ.2) THEN
407  nbo=nbo+1
408  END IF
409  END DO
410  ALLOCATE(xbpo(nbo),ybpo(nbo))
411 #ifdef W3_RTD
412  IF (isrtd) ALLOCATE(xtmp(nbo), ytmp(nbo), angtmp(nbo))
413 #endif
414  ALLOCATE (ipbpo(nbo,4),rdbpo(nbo,4))
415  ibo=0
416  DO isea=1,nsea
417  ix = mapsf(isea,1)
418  iy = mapsf(isea,2)
419  IF (mapsta(iy,ix).EQ.2) THEN
420  ibo=ibo+1
421  SELECT CASE ( gtype )
422  CASE ( rlgtype )
423  xbpo(ibo)=x0+sx*(ix-1)
424  ybpo(ibo)=y0+sy*(iy-1)
425  CASE ( clgtype )
426  xbpo(ibo)= xgrd(iy,ix)
427  ybpo(ibo)= ygrd(iy,ix)
428  CASE (ungtype)
429  xbpo(ibo)= xgrd(1,ix)
430  ybpo(ibo)= ygrd(1,ix)
431  END SELECT !GTYPE
432  END IF
433  END DO
434 #ifdef W3_RTD
435  !
436  IF (isrtd) THEN
437  ! Convert grid boundary cell locations to standard pole
438  xtmp = xbpo
439  ytmp = ybpo
440  CALL w3eqtoll(ytmp, xtmp, ybpo, xbpo, angtmp, polat, polon, nbo)
441  DEALLOCATE(xtmp, ytmp, angtmp)
442  ENDIF
443  !
444 #endif
445  !
446  OPEN(ndsb,file='nest.ww3',form='UNFORMATTED', convert=file_endian,status='unknown')
447  ALLOCATE(dimid(nbo2,3),dimln(nbo2,3),ncid(nbo2))
448 
449  ALLOCATE(lats(nbo2),lons(nbo2),station(16,nbo2))
450 
451  DO ip=1,nbo2
452  ! open file
453  OPEN(ndsc,file=trim(specfiles(ip)),form='UNFORMATTED', convert=file_endian, &
454  status='old',iostat=icode)
455  IF (icode.NE.0) THEN
456  lons(ip)=-999.
457  lats(ip)=-999.
458  WRITE (ndse,1010) trim(specfiles(ip))
459  CALL extcde ( 70 )
460  END IF
461 
462  iret=nf90_open(trim(specfiles(ip)),nf90_nowrite,ncid(ip))
463  WRITE(6,*) 'Opening file:',trim(specfiles(ip))
464  CALL check_err(iret)
465 
466  ! dimensions
467  iret=nf90_inq_dimid(ncid(ip),'time',dimid(ip,1))
468  CALL check_err(iret)
469  iret=nf90_inq_dimid(ncid(ip),'frequency',dimid(ip,2))
470  CALL check_err(iret)
471  iret=nf90_inq_dimid(ncid(ip),'direction',dimid(ip,3))
472  CALL check_err(iret)
473  iret=nf90_inquire_dimension(ncid(ip),dimid(ip,1),len=dimln(ip,1))
474  CALL check_err(iret)
475  iret=nf90_inquire_dimension(ncid(ip),dimid(ip,2),len=dimln(ip,2))
476  CALL check_err(iret)
477  iret=nf90_inquire_dimension(ncid(ip),dimid(ip,3),len=dimln(ip,3))
478  CALL check_err(iret)
479 
480  nti=dimln(ip,1)
481  nki=dimln(ip,2)
482  nthi=dimln(ip,3)
483 
484  IF (ip.EQ.1) THEN
485  nt1=nti
486  nk1=nki
487  nth1=nthi
488  nspec1 = nk1 * nth1
489  ALLOCATE(times(nt1))
490  ALLOCATE (freq(nk1),theta(nth1))
491  ALLOCATE (spec2d(nth1,nk1,nt1,nbo2))
492  ALLOCATE (abpin2(nk*nth,nt1,nbo2))
493 
494  ! instanciates time
495  refdate(:)=0.
496  iret=nf90_inq_varid(ncid(ip),"time",varid(1))
497  CALL check_err(iret)
498  iret=nf90_get_var(ncid(ip), varid(1), times(:))
499  CALL check_err(iret)
500  iret=nf90_get_att(ncid(ip),varid(1),"calendar",calendar)
501  IF ( iret/=nf90_noerr ) THEN
502  WRITE(ndse,951)
503  ELSE IF ((index(calendar, "standard").EQ.0) .AND. &
504  (index(calendar, "gregorian").EQ.0)) THEN
505  WRITE(ndse,952)
506  END IF
507  iret=nf90_get_att(ncid(ip),varid(1),"units",timeunits)
508  CALL u2d(timeunits,refdate,ierr)
509  CALL d2j(refdate,refjulday,ierr)
510 
511  ELSE
512  IF (nki.NE.nk1.OR.nthi.NE.nth1.OR.nt1.NE.nti &
513  ) GOTO 805
514  END IF
515 
516  ! position variables : lon/lat or x/y
517  IF ( flagll ) THEN
518  iret=nf90_inq_varid(ncid(ip), 'latitude', varid(2))
519  CALL check_err(iret)
520  iret=nf90_get_var(ncid(ip), varid(2), lats(ip))
521  CALL check_err(iret)
522  iret=nf90_inq_varid(ncid(ip), 'longitude', varid(3))
523  CALL check_err(iret)
524  iret=nf90_get_var(ncid(ip), varid(3), lons(ip))
525  CALL check_err(iret)
526  ELSE
527  iret=nf90_inq_varid(ncid(ip), 'y', varid(2))
528  CALL check_err(iret)
529  iret=nf90_get_var(ncid(ip), varid(2), lats(ip))
530  CALL check_err(iret)
531  iret=nf90_inq_varid(ncid(ip), 'x', varid(3))
532  CALL check_err(iret)
533  iret=nf90_get_var(ncid(ip), varid(3), lons(ip))
534  CALL check_err(iret)
535  END IF
536 
537  ! freq and dir variables
538  iret=nf90_inq_varid(ncid(ip),"frequency",varid(4))
539  CALL check_err(iret)
540  iret=nf90_get_var(ncid(ip),varid(4),freq)
541  CALL check_err(iret)
542  iret=nf90_inq_varid(ncid(ip),"direction",varid(5))
543  CALL check_err(iret)
544  iret=nf90_get_var(ncid(ip),varid(5),theta)
545  CALL check_err(iret)
546  theta=mod(2.5*pi-(pi/180)*theta,tpi)
547 
548  ! 2D spectra depending on station name or lat/lon
549  iret=nf90_inq_varid(ncid(ip),"efth",varid(7))
550  IF (iret.NE.0) iret=nf90_inq_varid(ncid(ip),"Efth",varid(7))
551  CALL check_err(iret)
552  iret=nf90_inquire_variable(ncid(ip),varid(7),xtype=vartype)
553  CALL check_err(iret)
554  iret=nf90_get_att(ncid(ip),varid(7),"_FillValue",fillval)
555  CALL check_err(iret)
556  iret=nf90_get_att(ncid(ip),varid(7),"scale_factor",factor)
557  IF (iret.NE.0) factor=1.
558  iret=nf90_get_att(ncid(ip),varid(7),"add_offset",offset)
559  IF (iret.NE.0) offset=0.
560  iret = nf90_inq_varid(ncid(ip), 'station_name', varid(6))
561  IF (iret.NE.0) THEN
562  ! efth(time, frequency, direction, latitude, longitude)
563  iret=nf90_get_var(ncid(ip),varid(7),spec2d(:,:,:,ip), &
564  start=(/1,1,1,1/),count=(/1,1,nthi,nki,nti/))
565  CALL check_err(iret)
566  ELSE
567  ! efth(time, station, frequency, direction)
568  iret=nf90_get_var(ncid(ip),varid(7),spec2d(:,:,:,ip), &
569  start=(/1,1,1,1/),count=(/nthi,nki,1,nti/))
570  CALL check_err(iret)
571  END IF
572  ! apply scale_factor and add_offset
573  IF (vartype.EQ.nf90_short) THEN
574  WHERE(spec2d(:,:,:,ip).NE.fillval) spec2d(:,:,:,ip)=(exp(spec2d(:,:,:,ip)*factor*log(10.)))-1e-12
575  ELSE
576  WHERE(spec2d(:,:,:,ip).NE.fillval) spec2d(:,:,:,ip)=(spec2d(:,:,:,ip)*factor)+offset
577  END IF
578 
579  ! close spectra file
580  iret=nf90_close(ncid(ip))
581  CALL check_err(iret)
582  !
583  END DO ! IP=1,NBO2
584 
585 
586 
587  !
588  !--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
589  ! 6. Checks on spectral discretization
590  ! reminder: fr(NK)=fr1*XFR**(NK-1)
591  !
592  fr1i=freq(1)
593  xfri=exp(alog(freq(nki)/freq(1))/(nki-1))
594  th1i=theta(1)
595 
596  spconv = nki.NE.nk .OR. nthi.NE.nth .OR. &
597  abs(xfri/xfr-1.).GT.0.01 .OR. &
598  abs(fr1i/fr1-1.).GT.0.01 .OR. &
599  abs(th1i-th(1)).GT.0.01*dth
600 
601  IF (verbose.GE.1) WRITE(ndso,*) 'SPCONV:', spconv, nki, nk, nthi, nth
602  !
603  !--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
604  ! 7. Loops on files and instanciate ABPIN2
605  !
606  IF ( .NOT. spconv ) THEN
607 
608  DO ip=1,nbo2
609  ! Copies spectrum in frequency and direction ranges
610  DO i=1,nk
611  DO j=1,nth
612  abpin2((i-1)*nth+j,:,ip)=spec2d(j,i,:,ip)*tpiinv
613  END DO
614  END DO
615  END DO ! IP=1,NBO2
616  !
617  ELSE
618  ALLOCATE(tmpspci(nki*nthi,nti))
619  ALLOCATE(tmpspco(nk*nth, nti))
620  DO ip=1,nbo2
621  DO i=1,nki
622  DO j=1,nthi
623  tmpspci((i-1)*nthi+j,:)=spec2d(j,i,:,ip)*tpiinv
624  END DO
625  END DO
626  CALL w3cspc ( tmpspci, nki, nthi, xfri, fr1i, th1i, &
627  tmpspco, nk, nth, xfr, fr1, th(1),&
628  nti, ndst, ndse, fachfe )
629  abpin2(:,:,ip)=tmpspco(:,:)
630  END DO
631  !
632  END IF
633  !
634  !--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
635  ! 8. Writes header
636  !
637  ! Writes header in nest.ww3 file
638  WRITE(ndsb) idstrbc, verbptbc, nk, nth, xfr, fr1, &
639  th(1), nbo
640  ipbpo(:,:)=1
641  rdbpo(:,1)=1.
642  rdbpo(:,2:4)=0.
643 
644  ! Loops on points
645  DO ip1=1,nbo
646  dmin=360.+180.
647  dmin2=360.+180.
648  ! Loops on files
649  DO ip=1,nbo2
650  ! Searches for the nearest 2 points where spectra are available
651  IF (flagll) THEN
652  dist=dist_sphere( lons(ip),lats(ip),xbpo(ip1),ybpo(ip1) )
653  ELSE
654  dist=sqrt((lons(ip)-xbpo(ip1))**2+(lats(ip)-ybpo(ip1))**2)
655  END IF
656  IF (dmin.EQ.(360.+180.)) THEN
657  IF(dist.LT.dmin) THEN
658  ipbpo(ip1,1)=ip
659  dmin=dist
660  END IF
661  ELSE
662  IF(dist.LT.dmin2) THEN
663  IF(dist.LT.dmin) THEN
664  ipbpo(ip1,2)=ipbpo(ip1,1)
665  dmin2=dmin
666  ipbpo(ip1,1)=ip
667  dmin=dist
668  ELSE
669  ipbpo(ip1,2)=ip
670  dmin2=dist
671  END IF
672  END IF
673  END IF
674  END DO ! IP1=1,NBO2
675  IF (verbose.GE.1) WRITE(ndso,*) 'DIST:',dmin,dmin2,ip1,ipbpo(ip1,1),ipbpo(ip1,2), &
676  lons(ipbpo(ip1,1)),lons(ipbpo(ip1,2)),xbpo(ip1), &
677  lats(ipbpo(ip1,1)),lats(ipbpo(ip1,2)),ybpo(ip1)
678 
679 
680  !
681  !--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
682  ! 9. Computes linear interpolation coefficient between the nearest 2 points
683  !
684  IF (interp.GT.1.AND.nbo2.GT.1) THEN
685  IF (flagll) THEN
686  dlon=lons(ipbpo(ip1,2))-lons(ipbpo(ip1,1))
687  dlat=lats(ipbpo(ip1,2))-lats(ipbpo(ip1,1))
688  dlo=xbpo(ip1)-lons(ipbpo(ip1,1))
689  IF (dlon.GT.180.) dlon=dlon-360
690  IF (dlon.LT.-180.) dlon=dlon+360
691  IF (dlo.GT.180.) dlo=dlo-360
692  IF (dlo.LT.-180.) dlo=dlo+360
693  dist=sqrt(dlon**2+dlat**2)
694  cos1=( dlo*dlon &
695  + (ybpo(ip1)-lats(ipbpo(ip1,1))) &
696  *dlat )/(dist**2)
697  ELSE
698  dist=sqrt((lons(ipbpo(ip1,1))-lons(ipbpo(ip1,2)))**2 &
699  +(lats(ipbpo(ip1,1))-lats(ipbpo(ip1,2)))**2)
700  cos1=( (xbpo(ip1)-lons(ipbpo(ip1,1))) &
701  *(lons(ipbpo(ip1,2))-lons(ipbpo(ip1,1))) &
702  + (ybpo(ip1)-lats(ipbpo(ip1,1))) &
703  *(lats(ipbpo(ip1,2))-lats(ipbpo(ip1,1))) )/(dist**2)
704  END IF
705  !COS2=( (XBPO(IP1)-LONS(IPBPO(IP1,2))) &
706  ! *(LONS(IPBPO(IP1,1))-LONS(IPBPO(IP1,2)))
707  ! + (YBPO(IP1)-LATS(IPBPO(IP1,2))) &
708  ! *(LATS(IPBPO(IP1,1))-LATS(IPBPO(IP1,2))))/(DIST**2)
709  rdbpo(ip1,1)=1-min(1.,max(0.,cos1))
710  rdbpo(ip1,2)=min(1.,max(0.,cos1))
711  ELSE
712  ! in this case: nearest point
713  rdbpo(ip1,1)=1.
714  rdbpo(ip1,2:4)=0.
715  END IF
716  IF (verbose.GE.1) WRITE(ndso,*) 'IPBP:',ip1,(ipbpo(ip1,j),j=1,4)
717  IF (verbose.GE.1) WRITE(ndso,*) 'RDBP:',ip1,(rdbpo(ip1,j),j=1,4)
718  !IF (VERBOSE.GE.1) WRITE(NDSO,*) 'RDBP:',COS1,DIST,DLON,DLO,DLAT,XBPO(IP1)-360.,LONS(IPBPO(IP1,1)),LONS(IPBPO(IP1,2))
719  END DO ! IP1=1,NBO
720 
721  WRITE(ndsb) (xbpo(i),i=1,nbo), &
722  (ybpo(i),i=1,nbo), &
723  ((ipbpo(i,j),i=1,nbo),j=1,4), &
724  ((rdbpo(i,j),i=1,nbo),j=1,4)
725 
726 
727  !
728  !--- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
729  ! 10. Loops on times and files and write to nest.ww3
730  !
731  DO it=1,nt1
732  curjulday=times(it)
733  IF (index(timeunits, "seconds").NE.0) curjulday=curjulday/86400.
734  IF (index(timeunits, "minutes").NE.0) curjulday=curjulday/1440.
735  IF (index(timeunits, "hours").NE.0) curjulday=curjulday/24.
736  curjulday=refjulday+curjulday
737 
738  ! convert julday to date and time
739  CALL j2d(curjulday,curdate,ierr)
740  CALL d2t(curdate,time,ierr)
741 
742  ! write to output file nest.ww3
743  WRITE(ndso,'(A,2I9,A,I6,A,G16.5)') 'Writing boundary data for time:', &
744  time, ' at ',nbo2,' points. Max.: ', maxval(abpin2(:,it,:))
745  WRITE(ndsb,iostat=ierr) time, nbo2
746  DO ip=1, nbo2
747  WRITE(ndsb) abpin2(:,it,ip)
748  END DO
749  END DO ! IT=0,NT1
750  CLOSE(ndsb)
751 
752  END IF ! INXOUT.EQ.'WRITE'
753 
754  GOTO 888
755 
756  !
757  ! Escape locations read errors :
758  !
759 
760 801 CONTINUE
761  WRITE (ndse,1001)
762  CALL extcde ( 61 )
763  !
764 802 CONTINUE
765  WRITE (ndse,1002) ierr
766  CALL extcde ( 62 )
767  !
768 803 CONTINUE
769  WRITE (ndse,1003) idtst, idstrbc
770  CALL extcde ( 63 )
771  !
772 804 CONTINUE
773  WRITE (ndse,1004)
774  CALL extcde ( 64 )
775  !
776 805 CONTINUE
777  WRITE (ndse,1005) trim(specfiles(ip)), nki, nk1, nthi, nth1, nti, nt1
778  CALL extcde ( 65 )
779  !
780 809 CONTINUE
781  WRITE (ndse,1009) file, ierr
782  CALL extcde ( 69 )
783  !
784 888 CONTINUE
785  WRITE (ndso,999)
786 
787 
788  !
789  ! Formats
790  !
791 900 FORMAT (/15x,' *** WAVEWATCH III Bounday input prep. *** '/ &
792  15x,'==============================================='/)
793  !
794 901 FORMAT ( ' Comment character is ''',a,''''/)
795  !
796 920 FORMAT ( ' Grid name : ',a/)
797  !
798 940 FORMAT ( ' Format version : ',a/)
799  !
800 941 FORMAT ( ' File type : ',a/)
801  !
802 951 FORMAT (/' *** WAVEWATCH III WARNING IN W3BOUNC : '/ &
803  ' CALENDAR ATTRIBUTE NOT DEFINED'/ &
804  ' IT MUST RESPECT STANDARD OR GREGORIAN CALENDAR')
805  !
806 952 FORMAT (/' *** WAVEWATCH III WARNING IN W3BOUNC : '/ &
807  ' CALENDAR ATTRIBUTE NOT MATCH'/ &
808  ' IT MUST RESPECT STANDARD OR GREGORIAN CALENDAR')
809  !
810 999 FORMAT (/' End of program '/ &
811  ' ========================================='/ &
812  ' WAVEWATCH III Boundary input '/)
813  !
814 1001 FORMAT (/' *** WAVEWATCH-III ERROR IN W3BOUNC : '/ &
815  ' PREMATURE END OF INPUT FILE'/)
816  !
817 1002 FORMAT (/' *** WAVEWATCH III ERROR IN W3BOUNC: '/ &
818  ' ERROR IN READING ',a,' FROM INPUT FILE'/ &
819  ' IOSTAT =',i5/)
820  !
821 1003 FORMAT (/' *** WAVEWATCH-III ERROR IN W3IOBC :'/ &
822  ' ILLEGAL IDSTR, READ : ',a/ &
823  ' CHECK : ',a/)
824  !
825 1004 FORMAT (/' *** WAVEWATCH-III ERROR IN W3BOUNC : '/ &
826  ' PREMATURE END OF NEST FILE'/)
827  !
828 1005 FORMAT (/' *** WAVEWATCH III ERROR IN W3BOUNC: '/ &
829  ' INCONSISTENT SPECTRAL DIMENSION FOR FILE ',a/ &
830  ' NKI =',i3,' DIFFERS FROM NK1 =',i3/ &
831  ' OR NTHI =',i3,' DIFFERS FROM NTH1 =',i3/ &
832  ' OR NTI =',i5,' DIFFERS FROM NT1 =',i5 /)
833  !
834 1009 FORMAT (/' *** WAVEWATCH III ERROR IN W3BOUNC : '/ &
835  ' ERROR IN OPENING SPEC FILE: ', a/ &
836  ' IOSTAT =',i5/)
837  !
838 1010 FORMAT (/' *** WAVEWATCH III ERROR IN W3BOUNC : '/ &
839  ' SPEC FILE DOES NOT EXIST : ',a/)
840  !
841  !
842  !/
843  !/ End of W3BOUNC ---------------------------------------------------- /
844  !/
845 END PROGRAM w3bounc
846 !/ ------------------------------------------------------------------- /
847 
848 
849 !==============================================================================
855 SUBROUTINE check_err(IRET)
856 
857  USE netcdf
858  USE w3odatmd, ONLY: ndse
859  USE w3servmd, ONLY: extcde
860 
861  IMPLICIT NONE
862 
863  INTEGER IRET
864 
865  IF (iret .NE. nf90_noerr) THEN
866  WRITE(ndse,*) ' *** WAVEWATCH III ERROR IN BOUNC :'
867  WRITE(ndse,*) ' NETCDF ERROR MESSAGE: '
868  WRITE(ndse,*) nf90_strerror(iret)
869  CALL extcde ( 59 )
870  END IF
871  RETURN
872 
873 END SUBROUTINE check_err
874 
875 !==============================================================================
w3gdatmd::nk
integer, pointer nk
Definition: w3gdatmd.F90:1230
constants::pi
real, parameter pi
PI Value of Pi.
Definition: constants.F90:71
w3servmd::nextln
subroutine nextln(CHCKC, NDSI, NDSE)
Definition: w3servmd.F90:222
include
cmake src_list cmake include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_switches.cmake) check_switches("$
Definition: CMakeLists.txt:15
w3gdatmd::dth
real, pointer dth
Definition: w3gdatmd.F90:1232
w3gdatmd::ygrd
double precision, dimension(:,:), pointer ygrd
Definition: w3gdatmd.F90:1205
w3adatmd
Define data structures to set up wave model auxiliary data for several models simultaneously.
Definition: w3adatmd.F90:26
w3gdatmd::ungtype
integer, parameter ungtype
Definition: w3gdatmd.F90:626
w3wdatmd
Define data structures to set up wave model dynamic data for several models simultaneously.
Definition: w3wdatmd.F90:18
w3gdatmd::rlgtype
integer, parameter rlgtype
Definition: w3gdatmd.F90:624
w3gdatmd::xgrd
double precision, dimension(:,:), pointer xgrd
Definition: w3gdatmd.F90:1205
w3gdatmd::sy
real, pointer sy
Definition: w3gdatmd.F90:1183
w3nmlbouncmd::w3nmlbounc
subroutine w3nmlbounc(NDSI, INFILE, NML_BOUND, IERR)
Definition: w3nmlbouncmd.F90:45
w3gdatmd::fachfe
real, pointer fachfe
Definition: w3gdatmd.F90:1232
w3gdatmd::gname
character(len=30), pointer gname
Definition: w3gdatmd.F90:1223
w3cspcmd
Convert spectra to new discrete spectral grid.
Definition: w3cspcmd.F90:21
w3odatmd::fnmpre
character(len=80) fnmpre
Definition: w3odatmd.F90:330
w3servmd::w3eqtoll
subroutine w3eqtoll(PHI_EQ, LAMBDA_EQ, PHI, LAMBDA, ANGLED, PHI_POLE, LAMBDA_POLE, POINTS)
Definition: w3servmd.F90:1224
w3gdatmd::th
real, dimension(:), pointer th
Definition: w3gdatmd.F90:1234
w3gdatmd::w3setg
subroutine w3setg(IMOD, NDSE, NDST)
Definition: w3gdatmd.F90:2152
w3odatmd::ndse
integer, pointer ndse
Definition: w3odatmd.F90:456
w3adatmd::w3seta
subroutine w3seta(IMOD, NDSE, NDST)
Select one of the WAVEWATCH III grids / models.
Definition: w3adatmd.F90:2645
w3wdatmd::w3ndat
subroutine w3ndat(NDSE, NDST)
Set up the number of grids to be used.
Definition: w3wdatmd.F90:210
w3gdatmd::polat
real, pointer polat
Definition: w3gdatmd.F90:1191
w3gdatmd::x0
real, pointer x0
Definition: w3gdatmd.F90:1183
w3gdatmd::nsea
integer, pointer nsea
Definition: w3gdatmd.F90:1097
w3gdatmd::clgtype
integer, parameter clgtype
Definition: w3gdatmd.F90:625
w3servmd
Definition: w3servmd.F90:3
w3iobcmd::verbptbc
character(len=10), parameter verbptbc
Definition: w3iobcmd.F90:76
w3wdatmd::w3setw
subroutine w3setw(IMOD, NDSE, NDST)
Select one of the WAVEWATCH III grids / models.
Definition: w3wdatmd.F90:660
constants::tpiinv
real, parameter tpiinv
TPIINV Inverse of 2*Pi.
Definition: constants.F90:74
w3odatmd::w3seto
subroutine w3seto(IMOD, NDSERR, NDSTST)
Definition: w3odatmd.F90:1523
w3gdatmd::nth
integer, pointer nth
Definition: w3gdatmd.F90:1230
w3iobcmd::idstrbc
character(len=32), parameter idstrbc
Definition: w3iobcmd.F90:77
w3odatmd
Definition: w3odatmd.F90:3
w3adatmd::w3naux
subroutine w3naux(NDSE, NDST)
Set up the number of grids to be used.
Definition: w3adatmd.F90:704
w3iobcmd
Processing of boundary data output.
Definition: w3iobcmd.F90:14
w3cspcmd::w3cspc
subroutine w3cspc(SP1, NFR1, NTH1, XF1, FR1, TH1, SP2, NFR2, NTH2, XF2, FR2, TH2, NSP, NDST, NDSE, FTL)
Convert a set of spectra to a new spectral grid.
Definition: w3cspcmd.F90:146
w3gdatmd::mapsf
integer, dimension(:,:), pointer mapsf
Definition: w3gdatmd.F90:1163
w3iogrmd::w3iogr
subroutine w3iogr(INXOUT, NDSM, IMOD, FEXT ifdef W3_ASCII
Reading and writing of the model definition file.
Definition: w3iogrmd.F90:117
file
file(STRINGS ${CMAKE_BINARY_DIR}/switch switch_strings) separate_arguments(switches UNIX_COMMAND $
Definition: CMakeLists.txt:3
w3iogrmd
Reading/writing of model definition file.
Definition: w3iogrmd.F90:20
check_err
subroutine check_err(IRET)
Check input return status for error value.
Definition: ww3_bounc.F90:856
w3gdatmd::fr1
real, pointer fr1
Definition: w3gdatmd.F90:1232
constants::tpi
real, parameter tpi
TPI 2*Pi.
Definition: constants.F90:72
w3servmd::strace
subroutine strace(IENT, SNAME)
Definition: w3servmd.F90:148
w3gdatmd::gtype
integer, pointer gtype
Definition: w3gdatmd.F90:1094
w3odatmd::ndso
integer, pointer ndso
Definition: w3odatmd.F90:456
w3gdatmd::w3nmod
subroutine w3nmod(NUMBER, NDSE, NDST, NAUX)
Definition: w3gdatmd.F90:1433
w3gdatmd::xfr
real, pointer xfr
Definition: w3gdatmd.F90:1232
w3gdatmd::y0
real, pointer y0
Definition: w3gdatmd.F90:1183
w3bounc
program w3bounc
Combines spectra files into a nest. ww3 file for boundary conditions.
Definition: ww3_bounc.F90:22
w3gdatmd::sx
real, pointer sx
Definition: w3gdatmd.F90:1183
constants
Define some much-used constants for global use (all defined as PARAMETER).
Definition: constants.F90:20
w3gdatmd
Definition: w3gdatmd.F90:16
constants::file_endian
character(*), parameter file_endian
FILE_ENDIAN Filled by preprocessor with 'big_endian', 'little_endian', or 'native'.
Definition: constants.F90:86
w3servmd::extcde
subroutine extcde(IEXIT, UNIT, MSG, FILE, LINE, COMM)
Definition: w3servmd.F90:736
w3odatmd::w3nout
subroutine w3nout(NDSERR, NDSTST)
Definition: w3odatmd.F90:561
w3servmd::itrace
subroutine itrace(NDS, NMAX)
Definition: w3servmd.F90:91
interp
subroutine interp(MXM, MYM, XC, IX21, IX22, IY21, IY22, RD11, RD12, RD21, RD22, FILLVALUE, FA)
Interpolate from a field read from file to the wave grid.
Definition: ww3_prnc.F90:2580
w3nmlbouncmd
Definition: w3nmlbouncmd.F90:3
w3timemd
Definition: w3timemd.F90:3
w3gdatmd::mapsta
integer, dimension(:,:), pointer mapsta
Definition: w3gdatmd.F90:1163
w3servmd::dist_sphere
real function dist_sphere(lo1, la1, lo2, la2)
Definition: w3servmd.F90:516
w3gdatmd::polon
real, pointer polon
Definition: w3gdatmd.F90:1191
w3nmlbouncmd::nml_bound_t
Definition: w3nmlbouncmd.F90:27
w3gdatmd::flagll
logical, pointer flagll
Definition: w3gdatmd.F90:1219