WAVEWATCH III  beta 0.0.1
w3strkmd Module Reference

Data Types

type  dat2d
 
type  mtchsys
 
type  neighbr
 
type  param
 
type  sysmemory
 
type  system
 
type  timsys
 
type  wind
 

Functions/Subroutines

subroutine wavetracking_nws_v2 (intype, tmax, tcur, filename, tstart, tend, dt, ntint, minlon, maxlon, minlat, maxlat, mxcwt, mycwt, dirKnob, perKnob, hsKnob, wetPts, seedLat, seedLon, dirTimeKnob, tpTimeKnob, paramFile, sysA, wsdat, maxSys, maxGroup)
 
subroutine spiraltrackv3 (wsdat, dirKnob, perKnob, wetPts, hsKnob, seedLat, seedLon, maxSys, sys)
 
subroutine timetrackingv2 (sysA, maxSys, tpTimeKnob, dirTimeKnob, ts0, maxGroup, dt, lonext, latext, maxI, maxJ)
 
subroutine findway (way, horizStepCount, vertStepCount, vertBorder, horizBorder, stepCount)
 
subroutine findnext (i, j, maxI, maxJ, way, vertBorder, horizBorder)
 
subroutine findsys (i, j, wsdat, maxSys, ngbrExt, maxI, maxJ, perKnob, dirKnob, hsKnob)
 
subroutine combinewavesystems (wsdat, maxSys, maxPts, maxI, maxJ, perKnob, dirKnob, hsKnob, combine, sys)
 
subroutine printfinalsys (wsdat, maxSys, actSysInd, maxI, maxJ, flag, sys)
 
subroutine combinesys (wsdat, sys, maxSys, maxI, maxJ, actSysInd, perKnob, dirKnob)
 
subroutine combinepartitionsv2 (dat)
 
real function mean_anglev2 (ang, ll)
 
real function mean_anglev3 (ang, hsign, ll)
 
subroutine unique (INARRAY, INSIZE, OUTARRAY, OUTSIZE)
 
subroutine sort (INARRAY, INSIZE, OUTARRAY, IY, DIRECTION)
 
subroutine setdiff (INARRAY1, INSIZE1, INARRAY2, INSIZE2, OUTARRAY, OUTSIZE)
 
subroutine intersect (INARRAY1, INSIZE1, INARRAY2, INSIZE2, OUTARRAY, OUTSIZE, IND1, IND2)
 
subroutine union (INARRAY1, INSIZE1, INARRAY2, INSIZE2, OUTARRAY, OUTSIZE)
 
integer function length (ARRAY, ARRSIZE, VAL)
 
integer function findfirst (ARRAY, ARRSIZE, VAL)
 
real function std (ARRAY, N)
 
recursive subroutine qsort (ARRAY, IDX, LO, HI)
 
recursive subroutine qsort_desc (ARRAY, IDX, LO, HI)
 
integer(kind=4) function swapi4 (INT4)
 
subroutine findijv4 (a, b, maxI, maxJ, indA, indB)
 

Function/Subroutine Documentation

◆ combinepartitionsv2()

subroutine w3strkmd::combinepartitionsv2 ( type(param), intent(inout)  dat)

Definition at line 4282 of file w3strkmd.F90.

4282  !/
4283  !/ +-----------------------------------+
4284  !/ | WAVEWATCH III NOAA/NCEP |
4285  !/ | A. J. van der Westhuysen |
4286  !/ | Jeff Hanson |
4287  !/ | Eve-Marie Devaliere |
4288  !/ | FORTRAN 95 |
4289  !/ | Last update : 4-Jan-2013 |
4290  !/ +-----------------------------------+
4291  !/
4292  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
4293  !/ by Jeff Hanson & Eve-Marie Devaliere
4294  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
4295  !/
4296  !/ Copyright 2009-2013 National Weather Service (NWS),
4297  !/ National Oceanic and Atmospheric Administration. All rights
4298  !/ reserved. WAVEWATCH III is a trademark of the NWS.
4299  !/ No unauthorized use without permission.
4300  !/
4301  IMPLICIT NONE
4302  !
4303  ! 1. Purpose :
4304  !
4305  ! Combine two partitions that have been assigned to the same system
4306  !
4307  ! 2. Method
4308  !
4309  ! Of all the partitions associated with a certain common system,
4310  ! add all the Hs values to the partition with the largest Hs,
4311  ! and delete the rest. NOTE that the tp and dir values of this
4312  ! maximum partition is not adjusted!
4313  !
4314  ! 3. Parameters :
4315  !
4316  ! Parameter list
4317  ! ----------------------------------------------------------------
4318  ! dat TYPE(param) in/out Input data structure (partitions set)
4319  ! to combine
4320  !
4321  TYPE(param) :: dat
4322 
4323  INTENT (IN OUT) dat
4324  !
4325  ! Local variables
4326  ! ----------------------------------------------------------------
4327  TYPE duplicate
4328  INTEGER :: val
4329  INTEGER :: ndup
4330  INTEGER :: ind(50)
4331  END TYPE duplicate
4332 
4333  TYPE(duplicate) :: dup(100) !40.PAR
4334  LOGICAL :: found
4335  INTEGER :: nsys, ndup, p, pp, maxInd, npart, s, ss, ppp
4336  REAL :: temp
4337  !
4338  ! 4. Subroutines used :
4339  !
4340  ! Name Type Module Description
4341  ! ----------------------------------------------------------------
4342  ! -
4343  !
4344  ! 5. Subroutines calling
4345  !
4346  ! findSys
4347  !
4348  ! 6. Error messages :
4349  !
4350  ! 7. Remarks :
4351  !
4352  ! 8. Structure :
4353  !
4354  ! -
4355  !
4356  ! 9. Switches :
4357  !
4358  ! None defined yet.
4359  !
4360  ! 10. Source code :
4361  !
4362  !/ ------------------------------------------------------------------- /
4363 
4364  ! Find indices in dat%sys(:) of all partition associated with
4365  ! the same wave system, and store them in the data structure
4366  ! dup(1:nsys). Here nsys is the number of systems for which duplicates
4367  ! were found, and dup(s)%ndup the number of partitions assigned
4368  ! to the same system s.
4369  nsys = 0
4370  dup(:)%ndup = 0
4371  dup(:)%val = 9999
4372  DO s = 1,100
4373  dup(s)%ind(:) = 0
4374  END DO
4375 
4376  npart = length(real(dat%ipart),SIZE(dat%ipart),real(0))
4377  DO p = 1, npart-1
4378  found = .false.
4379  IF (any(dat%sys(p).EQ.dup(:)%val)) cycle !found = .TRUE.
4380  DO pp = (p+1), npart
4381  IF (dat%sys(p).EQ.dat%sys(pp)) THEN
4382  ! First value
4383  IF (.NOT.found) THEN
4384  nsys=nsys+1
4385  dup(nsys)%val = dat%sys(p)
4386  dup(nsys)%ndup = 1
4387  dup(nsys)%ind(dup(nsys)%ndup) = p
4388  found = .true.
4389  END IF
4390  ! Subsequent duplicates
4391  IF (.NOT.any(pp.EQ.dup(nsys)%ind(:))) THEN
4392  dup(nsys)%ndup = dup(nsys)%ndup+1
4393  dup(nsys)%ind(dup(nsys)%ndup) = pp
4394  END IF
4395  END IF
4396  END DO
4397  END DO
4398 
4399  ! Now go through array of duplicates for each of n systems
4400  ! to add all the wave energy to the most energetic of the
4401  ! duplicates, and then remove the rest.
4402  maxind = 0
4403  temp = -9999.
4404  DO s = 1, nsys
4405  ! Find duplicate partition with the largest Hs (most energy)
4406  DO p = 1, dup(s)%ndup
4407  IF ( temp.LT.dat%hs(dup(s)%ind(p)) ) THEN
4408  temp = dat%hs(dup(s)%ind(p))
4409  maxind = p
4410  END IF
4411  END DO
4412 
4413  ! Add all energy (Hs) to this partition
4414  dat%hs(dup(s)%ind(maxind)) = &
4415  sqrt( sum(dat%hs(dup(s)%ind(1:dup(s)%ndup))**2) )
4416 
4417  ! Remove duplicate partitions which did not have the maximum Hs,
4418  ! and shift up indices to fill the gap
4419  DO p = 1, dup(s)%ndup
4420  ! Find index to remove
4421  IF (p.NE.maxind) THEN
4422  ! Shift up entries, deleting the duplicate partition
4423  ! REPLACE WITH CSHIFT(ARRAY, SHIFT, dim) ?
4424  dat%hs( dup(s)%ind(p):(npart-1) ) = &
4425  dat%hs( (dup(s)%ind(p)+1):npart)
4426  dat%tp( dup(s)%ind(p):(npart-1) ) = &
4427  dat%tp( (dup(s)%ind(p)+1):npart)
4428  dat%dir( dup(s)%ind(p):(npart-1) ) = &
4429  dat%dir( (dup(s)%ind(p)+1):npart)
4430  dat%dspr( dup(s)%ind(p):(npart-1) ) = &
4431  dat%dspr( (dup(s)%ind(p)+1):npart)
4432  ! dat%wf( dup(s)%ind(p):(npart-1) ) = &
4433  ! dat%wf( (dup(s)%ind(p)+1):npart)
4434  dat%sys( dup(s)%ind(p):(npart-1) ) = &
4435  dat%sys( (dup(s)%ind(p)+1):npart)
4436  dat%ipart( dup(s)%ind(p):(npart-1) ) = &
4437  dat%ipart( (dup(s)%ind(p)+1):npart)
4438  ! Shift up indices
4439  DO ss = 1, nsys
4440  DO ppp = 1, dup(ss)%ndup
4441  IF (dup(ss)%ind(ppp).GT.dup(s)%ind(p)) &
4442  dup(ss)%ind(ppp) = dup(ss)%ind(ppp)-1
4443  END DO
4444  END DO
4445  ! Add blank to end
4446  dat%hs(npart) = 9999.
4447  dat%tp(npart) = 9999.
4448  dat%dir(npart) = 9999.
4449  dat%dspr(npart) = 9999.
4450  ! dat%wf(npart) = 9999.
4451  dat%sys(npart) = 9999
4452  dat%ipart(npart) = 0
4453  END IF
4454  END DO
4455  END DO
4456 
4457  RETURN

References length().

Referenced by combinesys(), and findsys().

◆ combinesys()

subroutine w3strkmd::combinesys ( type(dat2d wsdat,
type(system), dimension(:), pointer  sys,
integer  maxSys,
integer, intent(in)  maxI,
integer, intent(in)  maxJ,
integer, dimension(:), allocatable  actSysInd,
real, intent(in)  perKnob,
real, intent(in)  dirKnob 
)

Definition at line 3683 of file w3strkmd.F90.

3683  !/
3684  !/ +-----------------------------------+
3685  !/ | WAVEWATCH III NOAA/NCEP |
3686  !/ | A. J. van der Westhuysen |
3687  !/ | Jeff Hanson |
3688  !/ | Eve-Marie Devaliere |
3689  !/ | FORTRAN 95 |
3690  !/ | Last update : 4-Jan-2013 |
3691  !/ +-----------------------------------+
3692  !/
3693  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
3694  !/ by Jeff Hanson & Eve-Marie Devaliere
3695  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
3696  !/
3697  !/ Copyright 2009-2013 National Weather Service (NWS),
3698  !/ National Oceanic and Atmospheric Administration. All rights
3699  !/ reserved. WAVEWATCH III is a trademark of the NWS.
3700  !/ No unauthorized use without permission.
3701  !/
3702  IMPLICIT NONE
3703  !
3704  ! 1. Purpose :
3705  !
3706  ! Combine wave systems
3707  !
3708  ! 2. Method
3709  !
3710  ! -
3711  !
3712  ! 3. Parameters :
3713  !
3714  ! Parameter list
3715  ! ----------------------------------------------------------------
3716  ! wsdat Type(dat2d) input Combined data structure
3717  ! maxI, maxJ Int input Maximum indices of wave field
3718  ! sys Type(system) output Final set of tracked systems, for one time level
3719  ! maxSys Int input Number of systems
3720  ! dirKnob Real input Parameter in direction for combining fields in space
3721  ! perKnob Real input Parameter in period for combining fields in space
3722  !
3723  TYPE(dat2d) :: wsdat !40.PAR
3724  TYPE(system), POINTER :: sys(:) !40.PAR
3725  INTEGER :: maxSys, maxI, maxJ !40.PAR
3726  INTEGER, ALLOCATABLE :: actSysInd(:)
3727  REAL :: perKnob ,dirKnob
3728  REAL :: dx, m1, m2
3729 
3730  INTENT (IN) maxi, maxj, perknob, dirknob !40.PAR
3731  ! INTENT (IN OUT) wsdat, sys, maxSys !40.PAR
3732  !
3733  ! Local variables
3734  ! ----------------------------------------------------------------
3735  ! ngbIndex Int Arr Array of neighbours
3736  !
3737  INTEGER, ALLOCATABLE :: sysSortedInd(:), sysOut(:)
3738  INTEGER, POINTER :: indSys1(:), indSys2(:)
3739  REAL, ALLOCATABLE :: sysOrdered(:), rounded(:)
3740  REAL, POINTER :: uniarr(:), difarr(:), allngbr(:)
3741  INTEGER :: leng, leng2, s, ss, so, ngb, lsys, lsys2, hh, i, j, &
3742  ii, jj, ind, ind2, nn, nbr, icEnd,ic,iii,iloop
3743  INTEGER :: myngbr, indMatch, matchSys, keep, replacedInd, &
3744  hhForIndMatch, lMatch, tot, outsize
3745  INTEGER :: ngbIndex(10000), keepInd(maxI*maxJ), oneLess(1000) !Array large enough?
3746  ! REAL :: Tb,deltaPerB,deltaDirB,absDir,absPer,absHs,absWf
3747  REAL :: Tb,deltaPerB,deltaDirB,deltaHsB,absDir,absPer,absHs
3748  LOGICAL :: file_exists
3749  INTEGER :: MASK(maxI,maxJ)
3750  REAL :: lonmean, latmean, DIST
3751  !061512 -----------------------------------------------
3752  LOGICAL :: ZIPMATCH
3753  INTEGER :: counter, count2, izp, izp2, in, jn, icnt, ngbrExt
3754  REAL :: T, ngb_tp, ngb_dir
3755  REAL :: ngbmatch(maxI*maxJ)
3756  TYPE(neighbr) :: ngbr(50)
3757  !061512 -----------------------------------------------
3758  REAL :: TEMP1, TEMP2
3759  INTEGER :: actSys
3760 
3761  !
3762  ! 4. Subroutines used :
3763  !
3764  ! Name Type Module Description
3765  ! ----------------------------------------------------------------
3766  ! SORT
3767  ! findIJV4
3768  ! UNIQUE
3769  ! combinePartitionsV2
3770  ! UNION
3771  ! SETDIFF
3772  !
3773  ! 5. Subroutines calling
3774  !
3775  ! combineWaveSystems
3776  !
3777  ! 6. Error messages :
3778  !
3779  ! 7. Remarks :
3780  !
3781  ! 8. Structure :
3782  !
3783  ! -
3784  !
3785  ! 9. Switches :
3786  !
3787  ! None defined yet.
3788  !
3789  ! 10. Source code :
3790  !
3791  !/ ------------------------------------------------------------------- /
3792  ! Initialize pointer (first use)
3793  NULLIFY(indsys1)
3794  NULLIFY(indsys2)
3795  ! Flag to combine systems on a point-by-point basis along boundary,
3796  ! instead of using mean values.
3797  zipmatch = .false.
3798  ngbrext = 1
3799  ! Combine systems on the basis of tpMean
3800  ALLOCATE( sysordered(maxsys) )
3801  ALLOCATE( syssortedind(maxsys) )
3802  ALLOCATE( sysout(maxsys) )
3803  ALLOCATE( rounded(maxsys) )
3804  ! Sort in descending Tp: the following improves the iterative combining in
3805  ! the special case that the wave period is constant over the domain, but
3806  ! tpMean is not because of truncation errors at very high decimals.
3807  rounded = real(int(sys(1:maxsys)%tpMean*1.e4))*1.e-4
3808  CALL sort(rounded,maxsys,sysordered,syssortedind,'D')
3809  sysout=sys(syssortedind)%sysInd
3810  IF (ALLOCATED(rounded)) DEALLOCATE(rounded)
3811 
3812  !051612 --- Land mask addition
3813  mask(:,:) = 0
3814  INQUIRE(file="sys_mask.ww3", exist=file_exists)
3815  IF (file_exists) THEN
3816  WRITE(20,*) '*** Using land mask'
3817  OPEN(unit=13,file='sys_mask.ww3',status='old')
3818  DO j = maxj,1,-1
3819  READ(13,*) (mask(i,j), i=1,maxi)
3820  END DO
3821  CLOSE(13)
3822  END IF
3823  !051612 --- Land mask addition
3824 
3825  !opt WRITE(20,*) 'SIZE(sysOut)=',SIZE(sysOut)
3826  DO so = 1, SIZE(sysout)
3827  ! WRITE(20,*) 'so =',so
3828  s = sysout(so)
3829  ss = findfirst(real(sys(:)%sysInd),SIZE(sys(:)%sysInd), &
3830  REAL(s))
3831  !opt WRITE(20,*) 's,ss=',s,ss
3832  ngbindex(:) = 0
3833  ii = 1
3834  leng = length(real(sys(ss)%ngbr),SIZE(sys(ss)%ngbr), &
3835  REAL(9999))
3836  ! Identify the indices of all the systems that neighbour the current system s,
3837  ! store in ngbIndex(:)
3838  DO ngb = 1, leng
3839  IF ( sys(ss)%ngbr(ngb).NE.s ) THEN
3840  myngbr = 1
3841  DO WHILE (myngbr.LE.SIZE(sysout))
3842  IF (sys(myngbr)%sysInd.EQ.sys(ss)%ngbr(ngb)) THEN
3843  ngbindex(ii) = myngbr
3844  ii = ii+1
3845  IF (ii.GT.1000) &
3846  WRITE(20,*) '*** WARNING: ngbIndex(:) exceeded!'
3847  END IF
3848  myngbr = myngbr+1
3849  END DO
3850  END IF
3851  END DO
3852  ii = ii-1
3853  !opt WRITE(20,*) so,'. sys =',s,', Tp =',sys(s)%tpMean, &
3854  !opt ', size=',sys(s)%nPoints,', #neighbours=',ii
3855 
3856  IF ( ii.GT.0 ) THEN
3857  DO ngb = 1, ii
3858  ! We first need to find the (i,j) points that are either common
3859  ! to both these systems, or at the boundary of the two systems. Here
3860  ! sys 1 will carry the 'ss' index and sys 2 the ngbIndex(ngb) index.
3861  CALL findijv4 (sys(ss),sys(ngbindex(ngb)), &
3862  maxi,maxj,indsys1,indsys2)
3863  IF ((SIZE(indsys1)>10).AND.(SIZE(indsys2)>10).AND. &
3864  (sys(ss)%nPoints.GT.sys(ngbindex(ngb))%nPoints)) &
3865  THEN
3866  lsys = SIZE(indsys1)
3867  lsys2 = SIZE(indsys2)
3868 
3869  !061512---------------Add zipper compare
3870  IF (zipmatch) THEN
3871  ! Omit small systems to save time
3872  IF ((sys(ss)%nPoints.LT.5).OR. &
3873  (sys(ngbindex(ngb))%nPoints.LT.5)) THEN
3874  cycle
3875  END IF
3876  dx=0.5*((wsdat%lon(2,1)-wsdat%lon(1,1)) + &
3877  (wsdat%lat(1,2)-wsdat%lat(1,1)))
3878  ngbmatch(:)=0.
3879  DO izp = 1,lsys
3880  ! Find neighbors of this point
3881  counter=0
3882  DO in=(sys(ss)%i(indsys1(izp))-ngbrext), &
3883  (sys(ss)%i(indsys1(izp))+ngbrext)
3884  DO jn=(sys(ss)%j(indsys1(izp))-ngbrext), &
3885  (sys(ss)%j(indsys1(izp))+ngbrext)
3886  counter=counter+1
3887  ngbr(counter)%i = in
3888  ngbr(counter)%j = jn
3889  END DO
3890  END DO
3891  ! Find these points in neighboring system
3892  ngb_tp = 0.
3893  ngb_dir = 0.
3894  count2 = 0
3895  DO izp2 = 1,lsys2
3896  DO icnt = 1,counter
3897  IF ((sys(ngbindex(ngb))%i(indsys2(izp2)) &
3898  .EQ.ngbr(icnt)%i).AND. &
3899  (sys(ngbindex(ngb))%j(indsys2(izp2)) &
3900  .EQ.ngbr(icnt)%j)) THEN
3901  count2 = count2+1
3902  ngb_tp = ngb_tp + &
3903  sys(ngbindex(ngb))%tp(indsys2(izp2))
3904  ngb_dir = ngb_dir + &
3905  sys(ngbindex(ngb))%dir(indsys2(izp2))
3906  END IF
3907  END DO
3908  END DO
3909  IF (count2.GT.0) THEN
3910  absper = abs(sys(ss)%tp(indsys1(izp))-ngb_tp/count2)
3911  absdir = abs(sys(ss)%dir(indsys1(izp))-ngb_dir/count2)
3912  t = sys(ss)%tp(indsys1(izp))
3913  m1 = -3.645*t + 63.211
3914  m1 = max(m1,10.)
3915  m2 = -0.346*t + 3.686
3916  m2 = max(m2,0.6)
3917  deltadirb = (m1*dx + dirknob)*1.
3918  deltaperb = (m2*dx + perknob)*1.
3919  IF ( (absper.LT.deltaperb).AND. &
3920  (absdir.LT.deltadirb) ) THEN
3921  ngbmatch(izp)=1.
3922  END IF
3923  END IF
3924  END DO
3925  ! If >80% of neighbors fall within criteria, system is matched
3926  IF ((sum(ngbmatch(1:lsys))/lsys).GT.0.50) THEN
3927  indmatch = ngbindex(ngb)
3928  matchsys = sys(indmatch)%sysInd
3929  ELSE
3930  cycle
3931  END IF
3932  ELSE
3933  !061512---------------------------------
3934 
3935  tb = max(sum(sys(ss)%tp(indsys1))/lsys, &
3936  sum(sys(ngbindex(ngb))%tp(indsys2))/lsys2)
3937  ! deltaPerB = (-0.06*Tb+2+perKnob)*1.5
3938  ! deltaDirB = (-Tb+(25+10*dirKnob))*1.5
3939  ! deltaPerB = (-0.06*Tb+2+2)*1.5
3940  ! deltaDirB = (-Tb+(25+10*2))*1.5
3941  dx=0.5*((wsdat%lon(2,1)-wsdat%lon(1,1)) + &
3942  (wsdat%lat(1,2)-wsdat%lat(1,1)))
3943  m1 = -3.523*tb + 64.081
3944  m1 = max(m1,10.)
3945  m2 = -0.337*tb + 3.732
3946  m2 = max(m2,0.6)
3947  !1stddev m1 = -2.219*Tb + 35.734
3948  !1stddev m1 = MAX(m1,5.)
3949  !1stddev m2 = -0.226*Tb + 2.213
3950  !1stddev m2 = MAX(m2,0.35)
3951  !5stddev m1 = -5.071*Tb + 90.688
3952  !5stddev m1 = MAX(m1,16.)
3953  !5stddev m2 = -0.467*Tb + 5.161
3954  !5stddev m2 = MAX(m2,1.0)
3955  deltadirb = (m1*1. + dirknob)*1.
3956  deltaperb = (m2*1. + perknob)*1.
3957  deltahsb = 0.50*sum(sys(ss)%hs(indsys1))/lsys
3958  ! deltaHsB = 0.25*SUM(sys(ss)%hs(indSys1))/lsys
3959 
3960  !051612 --- Land mask addition
3961  ! Option 1: If system centroid is near a land mask (e.g. 3 arc-deg),
3962  ! increase the tolerances
3963  IF (any(mask.EQ.1)) THEN
3964  lonmean = sum(sys(ss)%lon(indsys1))/lsys
3965  latmean = sum(sys(ss)%lat(indsys1))/lsys
3966  DO j = 1,maxj
3967  DO i = 1,maxi
3968  IF (mask(i,j).EQ.1) THEN
3969  ! Land point found. Compute distance to system centroid
3970  dist = sqrt((lonmean-wsdat%lon(i,j))**2 +&
3971  (latmean-wsdat%lat(i,j))**2)
3972  IF (dist.LT.3.) THEN
3973  ! System assumed to be influenced by land,
3974  ! increase tolerances to deltaDirB=30,deltaPerB=3
3975  ! deltaDirB = (m1*1. + 30)*1.
3976  ! deltaPerB = (m2*1. + 3)*1.
3977  deltadirb = (m1*1. + 30)*1.
3978  deltaperb = (m2*1. + 3)*1.
3979  !Remove dHs limitation from criteria
3980  deltahsb = 9999.
3981  GOTO 500
3982  END IF
3983  END IF
3984  END DO
3985  END DO
3986  END IF
3987 500 CONTINUE
3988  !051612 --- Land mask addition
3989 
3990  abshs = abs( sum(sys(ss)%hs(indsys1))/lsys - &
3991  sum(sys(ngbindex(ngb))%hs(indsys2))/lsys2 )
3992  absper = abs( sum(sys(ss)%tp(indsys1))/lsys - &
3993  sum(sys(ngbindex(ngb))%tp(indsys2))/lsys2 )
3994  absdir = abs( &
3995  mean_anglev2(sys(ss)%dir(indsys1),lsys) - &
3996  mean_anglev2(sys(ngbindex(ngb))%dir(indsys2), &
3997  lsys2) )
3998  IF (absdir.GT.180) absdir = 360.-absdir
3999  ! absWf = ABS( SUM(sys(ss)%wf(indSys1))/lsys - &
4000  ! SUM(sys(ngbIndex(ngb))%wf(indSys2))/lsys2 )
4001 
4002  IF ( (absper.LT.deltaperb).AND. &
4003  (absdir.LT.deltadirb).AND. &
4004  (abshs.LT.deltahsb) ) THEN
4005  indmatch = ngbindex(ngb)
4006  matchsys = sys(indmatch)%sysInd
4007  !opt WRITE(20,*) '-> Matched sys',s, &
4008  !opt 'with neighbor sys',matchSys
4009  ELSE
4010  cycle
4011  END IF
4012  !061512---------------------------------
4013  END IF
4014  !061512---------------------------------
4015 
4016  keep = 0
4017  keepind(:) = 0
4018 
4019  DO hh = 1, sys(ss)%nPoints
4020  ii = sys(ss)%i(hh)
4021  jj = sys(ss)%j(hh)
4022  ind = 0
4023  ind = findfirst(real(wsdat%par(ii,jj)%sys), &
4024  SIZE(wsdat%par(ii,jj)%sys),real(s)) !Shouldn't REAL(s) be matchSys...
4025  IF (ind.NE.0) THEN
4026  wsdat%par(ii,jj)%sys(ind)=matchsys !...and matchSys be s, (i.e. add the matching neigbour to the base?)
4027  END IF
4028  ! Remove the "-1" system from the set
4029  ind2 = 1
4030  oneless(:) = 9999 !Streamline this?
4031  leng = length(real(wsdat%par(ii,jj)%sys), &
4032  SIZE(wsdat%par(ii,jj)%sys),real(9999))
4033  DO ind = 1, leng
4034  IF ( wsdat%par(ii,jj)%sys(ind).NE.-1 ) THEN
4035  oneless(ind2) = wsdat%par(ii,jj)%sys(ind)
4036  ind2 = ind2+1
4037  END IF
4038  END DO
4039  ind2 = ind2-1
4040  ! Combine any partitions assigned to the same systems
4041  ! Check for duplicates
4042  IF (ind2.EQ.0) &
4043  WRITE(20,*) '***2.Calling UNIQUE w. len=0!'
4044  CALL unique(real(oneless(1:ind2)),ind2, &
4045  uniarr,outsize)
4046  IF (ASSOCIATED(uniarr)) DEALLOCATE(uniarr)
4047  IF (ind2.GT.outsize) THEN
4048  ! There is at least one duplicate, so combine systems
4049  CALL combinepartitionsv2(wsdat%par(ii,jj))
4050  ! Update the combined partitions values into the system we are keeping.
4051  ! Since partitions have been combined we don't know if the index is the same
4052  replacedind = &
4053  findfirst(real(wsdat%par(ii,jj)%sys(:)), &
4054  SIZE(wsdat%par(ii,jj)%sys(:)), &
4055  REAL(matchSys))
4056  hhforindmatch = 1
4057  DO WHILE (hhforindmatch.LE. &
4058  sys(indmatch)%nPoints)
4059  IF ( (sys(indmatch)%i(hhforindmatch) &
4060  .EQ.ii).AND. &
4061  (sys(indmatch)%j(hhforindmatch) &
4062  .EQ.jj) ) EXIT
4063  hhforindmatch = hhforindmatch + 1
4064  END DO
4065  sys(indmatch)%hs(hhforindmatch) = &
4066  wsdat%par(ii,jj)%hs(replacedind)
4067  sys(indmatch)%tp(hhforindmatch) = &
4068  wsdat%par(ii,jj)%tp(replacedind)
4069  sys(indmatch)%dir(hhforindmatch) = &
4070  wsdat%par(ii,jj)%dir(replacedind)
4071  sys(indmatch)%dspr(hhforindmatch) = &
4072  wsdat%par(ii,jj)%dspr(replacedind)
4073  ! sys(indMatch)%wf(hhForIndMatch) = &
4074  ! wsdat%par(ii,jj)%wf(replacedInd)
4075  ELSE
4076  keep = keep+1
4077  keepind(keep) = hh
4078  END IF
4079  END DO
4080  leng = length(real(sys(indmatch)%hs), &
4081  SIZE(sys(indmatch)%hs),real(9999.))
4082 
4083  ! Update system info
4084  ! ------------------
4085  ! First need to find which points were common to both systems =>
4086  ! keepInd since that means partitions have not been combined for those
4087  ! points as a result of the combination of those 2 systems =>
4088  ! distinct points
4089  ! keepInd = keepInd(1:keep)
4090  lmatch = length(real(sys(indmatch)%hs), &
4091  SIZE(sys(indmatch)%hs),real(9999.))
4092  tot = lmatch + keep
4093  CALL union (real(sys(indmatch)%ngbr), &
4094  SIZE(sys(indmatch)%ngbr), &
4095  REAL(sys(ss)%ngbr), &
4096  SIZE(sys(ss)%ngbr), &
4097  allngbr,outsize)
4098  CALL setdiff(allngbr,SIZE(allngbr), &
4099  REAL((/sys(indMatch)%sysInd, &
4100  sys(ss)%sysInd/)), &
4101  SIZE((/sys(indMatch)%sysInd, &
4102  sys(ss)%sysInd/)),difarr,outsize)
4103  sys(indmatch)%ngbr(:) = 9999
4104  outsize = min(outsize,size(sys(indmatch)%ngbr))
4105  sys(indmatch)%ngbr(1:outsize) = nint(difarr(1:outsize))
4106  IF (ASSOCIATED(allngbr)) DEALLOCATE(allngbr)
4107  IF (ASSOCIATED(difarr)) DEALLOCATE(difarr)
4108 
4109  leng = length(real(sys(indmatch)%i), &
4110  SIZE(sys(indmatch)%i),real(9999))
4111  sys(indmatch)%hsMean = sum((/ &
4112  sys(ss)%hs(keepind(1:keep)), &
4113  sys(indmatch)%hs(1:leng) /))/tot
4114  sys(indmatch)%tpMean = sum((/ &
4115  sys(ss)%tp(keepind(1:keep)), &
4116  sys(indmatch)%tp(1:leng) /))/tot
4117  sys(indmatch)%dirMean = &
4118  mean_anglev2((/ sys(ss)%dir(keepind(1:keep)), &
4119  sys(indmatch)%dir(1:leng) /),tot)
4120  !070512----------- Weight averages with Hm0 ---------------------
4121  temp1 = 0.
4122  temp2 = 0.
4123  DO iii = 1,keep
4124  temp1 = temp1 + (sys(ss)%hs(keepind(iii))**2)*&
4125  sys(ss)%hs(keepind(iii))
4126  temp2 = temp2 + (sys(ss)%hs(keepind(iii))**2)*&
4127  sys(ss)%tp(keepind(iii))
4128  END DO
4129  DO iii = 1,leng
4130  temp1 = temp1 + (sys(indmatch)%hs(iii)**2)*&
4131  sys(indmatch)%hs(iii)
4132  temp2 = temp2 + (sys(indmatch)%hs(iii)**2)*&
4133  sys(indmatch)%tp(iii)
4134  END DO
4135  sys(indmatch)%hsMean = temp1/max(sum((/ &
4136  sys(ss)%hs(keepind(1:keep))**2, &
4137  sys(indmatch)%hs(1:leng)**2 /)),0.001)
4138  sys(indmatch)%tpMean = temp2/max(sum((/ &
4139  sys(ss)%hs(keepind(1:keep))**2, &
4140  sys(indmatch)%hs(1:leng)**2 /)),0.001)
4141  sys(indmatch)%dirMean = &
4142  mean_anglev3((/ sys(ss)%dir(keepind(1:keep)), &
4143  sys(indmatch)%dir(1:leng) /), &
4144  (/ sys(ss)%hs(keepind(1:keep)), &
4145  sys(indmatch)%hs(1:leng) /),tot)
4146  !070512----------- Weight averages with Hm0 ---------------------
4147 
4148  sys(indmatch)%i(1:(keep+leng))= &
4149  (/sys(ss)%i(keepind(1:keep)), &
4150  sys(indmatch)%i(1:leng)/)
4151  sys(indmatch)%j(1:(keep+leng))= &
4152  (/sys(ss)%j(keepind(1:keep)), &
4153  sys(indmatch)%j(1:leng)/)
4154  sys(indmatch)%lat(1:(keep+leng)) = &
4155  (/sys(ss)%lat(keepind(1:keep)), &
4156  sys(indmatch)%lat(1:leng)/)
4157  sys(indmatch)%lon(1:(keep+leng)) = &
4158  (/sys(ss)%lon(keepind(1:keep)), &
4159  sys(indmatch)%lon(1:leng)/)
4160  sys(indmatch)%dir(1:(keep+leng)) = &
4161  (/sys(ss)%dir(keepind(1:keep)), &
4162  sys(indmatch)%dir(1:leng)/)
4163  sys(indmatch)%dspr(1:(keep+leng)) = &
4164  (/sys(ss)%dspr(keepind(1:keep)), &
4165  sys(indmatch)%dspr(1:leng)/)
4166  ! sys(indMatch)%wf(1:(keep+leng)) = &
4167  ! (/sys(ss)%wf(keepInd(1:keep)), &
4168  ! sys(indMatch)%wf(1:leng)/)
4169  sys(indmatch)%hs(1:(keep+leng)) = &
4170  (/sys(ss)%hs(keepind(1:keep)), &
4171  sys(indmatch)%hs(1:leng)/)
4172  sys(indmatch)%tp(1:(keep+leng)) = &
4173  (/sys(ss)%tp(keepind(1:keep)), &
4174  sys(indmatch)%tp(1:leng)/)
4175  sys(indmatch)%nPoints = &
4176  length(real(sys(indmatch)%i), &
4177  SIZE(sys(indmatch)%i),real(9999))
4178  ! Clear array of system that has just been combined with another
4179  sys(ss)%nPoints = 0
4180  sys(ss)%ngbr(:) = 9999
4181  WRITE(20,*) 'Deallocating sys',s
4182  DEALLOCATE( sys(ss)%hs ) !opt
4183  DEALLOCATE( sys(ss)%tp ) !opt
4184  DEALLOCATE( sys(ss)%dir ) !opt
4185  DEALLOCATE( sys(ss)%dspr ) !opt
4186  ! DEALLOCATE( sys(ss)%wf ) !opt
4187  DEALLOCATE( sys(ss)%i ) !opt
4188  DEALLOCATE( sys(ss)%j ) !opt
4189  DEALLOCATE( sys(ss)%lat ) !opt
4190  DEALLOCATE( sys(ss)%lon ) !opt
4191  ! DEALLOCATE( sys(ss)%hsMean ) !opt
4192  ! DEALLOCATE( sys(ss)%tpMean ) !opt
4193  ! DEALLOCATE( sys(ss)%dirMean ) !opt
4194 
4195  ! Loop through wsdat to update neighbouring system values
4196  DO i = 1, maxi
4197  DO j = 1, maxj
4198  ind = findfirst(real(wsdat%par(i,j)%ngbrSys), &
4199  SIZE(wsdat%par(i,j)%ngbrSys),real(s))
4200  IF (ind.NE.0) THEN
4201  wsdat%par(i,j)%ngbrSys(ind)=matchsys
4202  END IF
4203  leng = length(real(wsdat%par(i,j)%ngbrSys), &
4204  SIZE(wsdat%par(i,j)%ngbrSys),real(9999))
4205  IF (leng.GT.0) THEN
4206  CALL unique( &
4207  REAL(wsdat%par(i,j)%ngbrSys(1:leng)), &
4208  leng,uniarr,outsize)
4209  wsdat%par(i,j)%ngbrSys(:) = 9999
4210  wsdat%par(i,j)%ngbrSys(1:outsize) = &
4211  nint(uniarr)
4212  IF (ASSOCIATED(uniarr)) DEALLOCATE(uniarr)
4213  ELSE
4214  wsdat%par(i,j)%ngbrSys(:) = 9999
4215  END IF
4216  END DO
4217  END DO
4218 
4219  ! Update neigbors in sys structure
4220  DO nn = 1, maxsys
4221  nbr = findfirst(real(sys(nn)%ngbr), &
4222  SIZE(sys(nn)%ngbr),real(s))
4223  IF (nbr.NE.0) THEN
4224  ! WRITE(20,*) 'update'
4225  sys(nn)%ngbr(nbr)=matchsys
4226  END IF
4227  leng2 = length(real(sys(nn)%ngbr), &
4228  SIZE(sys(nn)%ngbr),real(9999))
4229  IF (leng2.GT.0) THEN
4230  CALL unique(real(sys(nn)%ngbr(1:leng2)), &
4231  leng2,uniarr,outsize)
4232  sys(nn)%ngbr(:) = 9999
4233  sys(nn)%ngbr(1:outsize) = nint(uniarr)
4234  IF (ASSOCIATED(uniarr)) DEALLOCATE(uniarr)
4235  ! WRITE(20,*) 'has now ngbr: ', &
4236  ! sys(nn)%ngbr(1:outsize)
4237  END IF
4238  END DO
4239  EXIT
4240  END IF
4241 
4242 
4243  IF (ASSOCIATED(indsys1)) DEALLOCATE(indsys1)
4244  IF (ASSOCIATED(indsys2)) DEALLOCATE(indsys2)
4245  END DO
4246  END IF
4247  END DO
4248 
4249  IF (ALLOCATED(sysordered)) DEALLOCATE(sysordered)
4250  IF (ALLOCATED(syssortedind)) DEALLOCATE(syssortedind)
4251  IF (ALLOCATED(sysout)) DEALLOCATE(sysout)
4252 
4253  ! Compile array index of active systems in sys
4254  actsys = 0
4255  DO ic = 1,maxsys
4256  IF (sys(ic)%nPoints>0) actsys = actsys + 1
4257  END DO
4258  IF (ALLOCATED(actsysind)) DEALLOCATE(actsysind)
4259  ALLOCATE( actsysind(actsys) )
4260  actsys = 0
4261  DO ic = 1,maxsys
4262  IF (sys(ic)%nPoints>0) THEN
4263  actsys = actsys + 1
4264  actsysind(actsys) = sys(ic)%sysInd
4265  END IF
4266  END DO
4267 
4268  !opt WRITE(20,*) 'actSys =',actSys
4269  !opt WRITE(20,*) 'actSysInd =',actSysInd
4270  !opt DO ic = 1,SIZE(actSysInd)
4271  !opt s = actSysInd(ic)
4272  !opt WRITE(20,*) 'sys(',s,')%sysInd =',sys(s)%sysInd
4273  !opt END DO
4274  WRITE(20,*) 'Leaving combineSys...'
4275 
4276  RETURN

References combinepartitionsv2(), file(), findfirst(), findijv4(), length(), mean_anglev2(), mean_anglev3(), setdiff(), sort(), union(), and unique().

Referenced by combinewavesystems().

◆ combinewavesystems()

subroutine w3strkmd::combinewavesystems ( type(dat2d), intent(inout)  wsdat,
integer, intent(inout)  maxSys,
integer, intent(in)  maxPts,
integer, intent(in)  maxI,
integer, intent(in)  maxJ,
real  perKnob,
real  dirKnob,
real, intent(in)  hsKnob,
integer, intent(in)  combine,
type(system), dimension(:), pointer  sys 
)

Definition at line 3209 of file w3strkmd.F90.

3209  !/
3210  !/ +-----------------------------------+
3211  !/ | WAVEWATCH III NOAA/NCEP |
3212  !/ | A. J. van der Westhuysen |
3213  !/ | Jeff Hanson |
3214  !/ | Eve-Marie Devaliere |
3215  !/ | FORTRAN 95 |
3216  !/ | Last update : 4-Jan-2013 |
3217  !/ +-----------------------------------+
3218  !/
3219  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
3220  !/ by Jeff Hanson & Eve-Marie Devaliere
3221  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
3222  !/
3223  !/ Copyright 2009-2013 National Weather Service (NWS),
3224  !/ National Oceanic and Atmospheric Administration. All rights
3225  !/ reserved. WAVEWATCH III is a trademark of the NWS.
3226  !/ No unauthorized use without permission.
3227  !/
3228  IMPLICIT NONE
3229  !
3230  ! 1. Purpose :
3231  !
3232  ! Combine wave systems. Then remove small and low-energy systems from set,
3233  ! based on the parameters maxPts and maxHgt.
3234  !
3235  ! 2. Method
3236  !
3237  ! -
3238  !
3239  ! 3. Parameters :
3240  !
3241  ! Parameter list
3242  ! ----------------------------------------------------------------
3243  ! wsdat Type(dat2d) output Combined wave system data structure
3244  ! sys Type(system) output Final set of tracked systems, for one time level
3245  ! maxI, maxJ Int input Maximum indices of wave field
3246  ! maxSys Int input Maximum number of systems identified
3247  ! maxPts Int input Number of points req for valid system
3248  ! hsKnob Real input Parameter for identifying valid system
3249  ! combine Int input Toggle: 1=combine systems; 0=do not combine
3250 
3251  TYPE(dat2d) :: wsdat
3252  TYPE(system), POINTER :: sys(:), systemp(:)
3253  INTEGER :: maxSys, maxPts, maxI, maxJ, combine
3254  REAL :: perKnob ,dirKnob, hsKnob
3255 
3256  INTENT (IN) maxpts, maxi, maxj, hsknob, combine
3257  INTENT (IN OUT) wsdat, maxsys !In the Matlab code maxSys is only input ???
3258  ! INTENT (OUT) sys
3259  !
3260  ! Local variables
3261  ! ----------------------------------------------------------------
3262  ! nSys Int Number of wave systems (for checking iterative combining loop)
3263  !
3264  LOGICAL :: found
3265  INTEGER, ALLOCATABLE :: sysOut(:)
3266  INTEGER, ALLOCATABLE :: actSysInd(:)
3267  INTEGER :: iter, ok, nSys, mS, s, so, ss, ind, leng, &
3268  iw, jw, iloop
3269  INTEGER :: actSys
3270  REAL :: dev, hsCmp, maxHgt, temp(5)
3271  !
3272  ! 4. Subroutines used :
3273  !
3274  ! Name Type Module Description
3275  ! ----------------------------------------------------------------
3276  ! printFinalSys
3277  ! combineSys
3278  !
3279  ! 5. Subroutines calling
3280  !
3281  ! spiralTrackV3
3282  !
3283  ! 6. Error messages :
3284  !
3285  ! 7. Remarks :
3286  !
3287  ! 8. Structure :
3288  !
3289  ! -
3290  !
3291  ! 9. Switches :
3292  !
3293  ! None defined yet.
3294  !
3295  ! 10. Source code :
3296  !
3297  !/ ------------------------------------------------------------------- /
3298 
3299  !012912 WRITE(20,*) 'maxSys,maxPts,maxI,maxJ,hsKnob,combine =', &
3300  !012912 maxSys,maxPts,maxI,maxJ,hsKnob,combine
3301 
3302  ! Set up initial index array of active systems
3303  IF (.NOT.ALLOCATED(actsysind)) ALLOCATE( actsysind(maxsys) )
3304  actsysind(1:maxsys) = (/ (ind, ind = 1, maxsys) /)
3305  !opt WRITE(20,*) 'actSysInd =',actSysInd
3306 
3307  IF (combine.EQ.1) THEN
3308  ! Combine wave systems
3309  WRITE(20,*) 'Calling printFinalSys...'
3310  CALL printfinalsys (wsdat,maxsys,actsysind,maxi,maxj,1,sys)
3311  iter=0
3312  ok=0
3313  ! Keep on combining wave systems until all possible combining
3314  ! has been carried out (based on the combining criteria)
3315  DO WHILE (ok.EQ.0)
3316  iter = iter+1
3317  ! No of systems before combining
3318  IF (ALLOCATED(actsysind)) THEN
3319  nsys = SIZE(actsysind)
3320  ELSE
3321  nsys = maxsys
3322  END IF
3323  WRITE(20,'(A,A,I3,A,I5,A)') 'Calling combineSys for ', &
3324  'iteration',iter,' (maxSys =',nsys,').'
3325 
3326  !opt WRITE(20,*) 'SIZE(sys)=',SIZE(sys)
3327  CALL combinesys (wsdat,sys,maxsys,maxi,maxj, &
3328  actsysind,perknob,dirknob)
3329  ! No of systems after combining
3330  !opt WRITE(20,*) 'maxSys,nSys,SIZE(actSysInd) =', &
3331  !opt maxSys,nSys,SIZE(actSysInd)
3332  ! IF (maxSys.EQ.nSys) ok = 1
3333  IF (SIZE(actsysind).EQ.nsys) ok = 1
3334  END DO
3335  ELSE
3336  ! Do not combine wave systems
3337  CALL printfinalsys (wsdat,maxsys,actsysind,maxi,maxj,3,sys)
3338  END IF
3339 
3340  ! Remove small and low-energy systems from set, based on
3341  ! the parameters maxPts and maxHgt.
3342  ! ALLOCATE( sysOut(maxSys) )
3343  ! sysOut = sys(1:maxSys)%sysInd
3344  ! mS = maxSys
3345  ms = SIZE(actsysind)
3346  ss = 1
3347  WRITE(20,*) 'Filtering the set of',ms,'systems on size and mag.'
3348 
3349  DO so = 1, ms
3350  s = actsysind(so)
3351  !opt NOTE: if we deallocate the individual records without
3352  !opt compressing sys, then s and sysInd will remain the same
3353  ss = s
3354 
3355  leng = length(sys(ss)%hs,SIZE(sys(ss)%hs),9999.)
3356  dev = std(sys(ss)%hs(1:leng),leng)
3357  hscmp = sys(ss)%hsMean + 2.*dev
3358  maxhgt = hsknob
3359 
3360  IF ( (hscmp.LT.maxhgt).OR.(sys(ss)%nPoints.LT.maxpts) ) THEN
3361  ! Remove system, and shift up indices to fill the gap
3362  DO ind = 1, maxsys
3363  ! Find index to remove
3364  IF (ind.EQ.ss) THEN
3365  ! Shift up entries, deleting the duplicate partition
3366  ! REPLACE WITH CSHIFT(ARRAY, SHIFT, dim)?
3367  ! IF (ind.LT.maxSys) &
3368  ! sys( ind:(maxSys-1) ) = sys( (ind+1):maxSys )
3369  IF (ind.LE.maxsys) THEN
3370  ! Since we use pointers, we have to copy each index and
3371  ! field individually. Otherwise memory corruption occurs.
3372  DO iloop = ind,ind
3373  sys(iloop)%sysInd = 9999
3374  sys(iloop)%nPoints = 0
3375  sys(iloop)%grp = 9999
3376  DEALLOCATE( sys(iloop)%hs )
3377  DEALLOCATE( sys(iloop)%tp )
3378  DEALLOCATE( sys(iloop)%dir )
3379  DEALLOCATE( sys(iloop)%dspr )
3380  ! DEALLOCATE( sys(iloop)%wf )
3381  DEALLOCATE( sys(iloop)%i )
3382  DEALLOCATE( sys(iloop)%j )
3383  DEALLOCATE( sys(iloop)%lat )
3384  DEALLOCATE( sys(iloop)%lon )
3385  ! DEALLOCATE( sys(iloop)%hsMean )
3386  ! DEALLOCATE( sys(iloop)%tpMean )
3387  ! DEALLOCATE( sys(iloop)%dirMean )
3388  ! DEALLOCATE( sys(iloop)%ngbr )
3389  END DO
3390  END IF
3391  END IF
3392  END DO
3393 
3394  ! Update wsdat as well
3395  DO iw = 1, maxi
3396  DO jw = 1, maxj
3397  leng = length(real(wsdat%par(iw,jw)%sys), &
3398  SIZE(wsdat%par(iw,jw)%sys),real(9999))
3399  ind = 1
3400  found = .false.
3401  ! Identify system index (there are no duplicate
3402  ! systems at this point.
3403  DO WHILE (ind.LE.leng)
3404  IF ( wsdat%par(iw,jw)%sys(ind).EQ.s ) THEN
3405  found = .true.
3406  EXIT
3407  END IF
3408  ind = ind + 1
3409  END DO
3410  IF (found) THEN
3411  ! Blank out used record
3412  wsdat%par(iw,jw)%sys(ind) = 9999
3413  wsdat%par(iw,jw)%ipart(ind) = 9999
3414  END IF
3415  END DO
3416  END DO
3417  END IF
3418  END DO
3419 
3420  ! Compile array index of active systems in sys
3421  actsys = 0
3422  DO so = 1,maxsys
3423  IF (sys(so)%nPoints>0) actsys = actsys + 1
3424  END DO
3425  IF (ALLOCATED(actsysind)) DEALLOCATE(actsysind)
3426  ALLOCATE( actsysind(actsys) )
3427  actsys = 0
3428  DO so = 1,maxsys
3429  IF (sys(so)%nPoints>0) THEN
3430  actsys = actsys + 1
3431  actsysind(actsys) = sys(so)%sysInd
3432  END IF
3433  END DO
3434 
3435  !opt WRITE(20,*) 'actSysInd =',actSysInd
3436  DO so = 1,SIZE(actsysind)
3437  s = actsysind(so)
3438  !opt WRITE(20,*) 'sys(',s,')%sysInd =',sys(s)%sysInd
3439  END DO
3440 
3441  CALL printfinalsys (wsdat,maxsys,actsysind,maxi,maxj,1,sys)
3442  !opt WRITE(20,*) 'actSysInd =',actSysInd
3443  !opt DO so = 1,maxSys
3444  !opt WRITE(20,*) 'sys(',so,')%sysInd =',sys(so)%sysInd, &
3445  !opt ', sys(',so,')%nPoints =',sys(so)%nPoints
3446  !opt END DO
3447 
3448  RETURN

References combinesys(), length(), printfinalsys(), and std().

Referenced by spiraltrackv3().

◆ findfirst()

integer function w3strkmd::findfirst ( real, dimension(arrsize)  ARRAY,
integer  ARRSIZE,
real  VAL 
)

Definition at line 5495 of file w3strkmd.F90.

5495  !/
5496  !/ +-----------------------------------+
5497  !/ | WAVEWATCH III NOAA/NCEP |
5498  !/ | A. J. van der Westhuysen |
5499  !/ | Jeff Hanson |
5500  !/ | Eve-Marie Devaliere |
5501  !/ | FORTRAN 95 |
5502  !/ | Last update : 4-Jan-2013 |
5503  !/ +-----------------------------------+
5504  !/
5505  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
5506  !/ by Jeff Hanson & Eve-Marie Devaliere
5507  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
5508  !/
5509  !/ Copyright 2009-2013 National Weather Service (NWS),
5510  !/ National Oceanic and Atmospheric Administration. All rights
5511  !/ reserved. WAVEWATCH III is a trademark of the NWS.
5512  !/ No unauthorized use without permission.
5513  !/
5514  IMPLICIT NONE
5515  !
5516  ! 1. Purpose :
5517  !
5518  ! Fast algorithm to find the *first* index IND in ARRAY
5519  ! for which ARRAY(IND) = VAL. Use only when there are
5520  ! no duplicates in ARRAY!
5521  !
5522  ! 3. Parameters :
5523  !
5524  ! Parameter list
5525  ! ----------------------------------------------------------------
5526  INTEGER :: ARRSIZE
5527  REAL :: ARRAY(ARRSIZE)
5528  REAL :: VAL
5529  !
5530  ! Local variables
5531  ! ----------------------------------------------------------------
5532  INTEGER :: IND
5533  !
5534  ! 10. Source code :
5535  !
5536  !/ ------------------------------------------------------------------- /
5537  ind = 1
5538  DO WHILE (ind.LE.arrsize)
5539  IF ( array(ind).EQ.val ) EXIT
5540  ind = ind + 1
5541  END DO
5542  IF (ind.GT.arrsize) THEN
5543  findfirst = 0
5544  ELSE
5545  findfirst = ind
5546  ENDIF
5547 
5548  RETURN

Referenced by combinesys(), findsys(), and timetrackingv2().

◆ findijv4()

subroutine w3strkmd::findijv4 ( type(system), intent(in)  a,
type(system), intent(in)  b,
integer, intent(in)  maxI,
integer, intent(in)  maxJ,
integer, dimension(:), pointer  indA,
integer, dimension(:), pointer  indB 
)

Definition at line 5893 of file w3strkmd.F90.

5893  !/
5894  !/ +-----------------------------------+
5895  !/ | WAVEWATCH III NOAA/NCEP |
5896  !/ | A. J. van der Westhuysen |
5897  !/ | Jeff Hanson |
5898  !/ | Eve-Marie Devaliere |
5899  !/ | FORTRAN 95 |
5900  !/ | Last update : 03-Mar-2017 |
5901  !/ +-----------------------------------+
5902  !/
5903  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
5904  !/ by Jeff Hanson & Eve-Marie Devaliere
5905  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
5906  !/ 03-Mar-2017 : Calls to INTERSECT and UNION ( version 5.16 )
5907  !/ replaced (S. Zieger, BoM, Australia)
5908  !/
5909  !/ Copyright 2009-2013 National Weather Service (NWS),
5910  !/ National Oceanic and Atmospheric Administration. All rights
5911  !/ reserved. WAVEWATCH III is a trademark of the NWS.
5912  !/ No unauthorized use without permission.
5913  !/
5914  IMPLICIT NONE
5915  !
5916  ! 1. Purpose :
5917  !
5918  ! Find a(i,j) indices of system "a" that lie over or along the
5919  ! fringes of system "b".
5920  !
5921  ! 2. Method
5922  !
5923  ! (i) Use an index matrix to map locations of wave systems in B
5924  ! (ii) Avoid multiple use of INTERSECT and UNION as in findIJV3
5925  !
5926  ! 3. Parameters :
5927  !
5928  ! Parameter list
5929  ! ----------------------------------------------------------------
5930  ! a, b Type(system) input Final set of tracked systems, for one time level
5931  ! maxI Int input Number rows indices of wave field
5932  ! maxJ Int input Number column indices of wave field
5933  ! indA*, indB* Int.A. output Pointer array of indices for combining systems
5934  !
5935  TYPE(system) :: a, b
5936  INTEGER :: maxI, maxJ
5937  INTEGER, POINTER :: indA(:), indB(:)
5938  !
5939  INTENT (IN) a, b, maxi,maxj
5940  !
5941  ! Local variables
5942  ! ----------------------------------------------------------------
5943  ! posB Int Neighbour index
5944  ! posB_MM Int Neighbour index (-1,-1)
5945  ! posB_MP Int Neighbour index (-1,+1)
5946  ! posB_PM Int Neighbour index (+1,-1)
5947  ! posB_PP Int Neighbour index (+1,+1)
5948  ! tmpA*, tmpB* Int.A. Array of indices for combining
5949  ! systems
5950  !
5951  INTEGER :: LENG_AI,LENG_BI
5952  INTEGER :: OUTA,OUTB,I,J,IND,OUTDUMB
5953  INTEGER :: POSB,POSB_MM,POSB_PM,POSB_MP,POSB_PP
5954  INTEGER :: IND_B2(maxI,maxJ)
5955  REAL,ALLOCATABLE :: TMPA(:),DUMA(:),TMPB(:)
5956  REAL,POINTER :: DUMB(:)
5957  LOGICAL :: FOUND
5958  !
5959  ! 4. Subroutines used :
5960  !
5961  ! Name Type Scope Description
5962  ! ----------------------------------------------------------------
5963  ! QSORT Subr. Private Quicksort algorithm
5964  ! UNIQUE Subr. Private Return sorted unique numbers of an array
5965  !
5966  ! 5. Subroutines calling
5967  !
5968  ! 6. Error messages :
5969  !
5970  ! 7. Remarks :
5971  !
5972  ! 8. Structure :
5973  !
5974  ! 9. Switches :
5975  !
5976  ! 10. Source code :
5977  !
5978  !/ ------------------------------------------------------------------- /
5979  !
5980  NULLIFY(dumb)
5981  !
5982  IF (ASSOCIATED(inda)) DEALLOCATE(inda)
5983  IF (ASSOCIATED(indb)) DEALLOCATE(indb)
5984  !
5985  leng_ai = length(real(a%i),SIZE(a%i),real(9999))
5986  leng_bi = length(real(b%i),SIZE(b%i),real(9999))
5987  !
5988  ALLOCATE(tmpa(leng_ai))
5989  ALLOCATE(tmpb(5*leng_ai))
5990  !
5991  tmpa(:) = 9999.
5992  tmpb(:) = 9999.
5993  !
5994  outa = 0
5995  outb = 0
5996  ind_b2(:,:) = 0
5997  !
5998  DO ind=1,leng_bi
5999  i = b%I(ind)
6000  j = b%J(ind)
6001  IF (ind_b2(i,j).EQ.0) ind_b2(i,j) = ind
6002  END DO
6003  !
6004  DO ind=1,leng_ai
6005  i = a%I(ind)
6006  j = a%J(ind)
6007  posb = ind_b2(i,j)
6008  posb_mm = 0
6009  posb_pp = 0
6010  posb_mp = 0
6011  posb_pm = 0
6012  IF (i.GT.1.AND.j.GT.1) posb_mm = ind_b2(i-1,j-1)
6013  IF (i.GT.1.AND.j.LT.maxj) posb_mp = ind_b2(i-1,j+1)
6014  IF (i.LT.maxi.AND.j.LT.maxj) posb_pp = ind_b2(i+1,j+1)
6015  IF (i.LT.maxi.AND.j.GT.1) posb_pm = ind_b2(i+1,j-1)
6016 
6017  found = .false.
6018  IF (posb.NE.0) THEN
6019  outb = outb + 1
6020  tmpb(outb) = real(posb)
6021  IF (.NOT.found) THEN
6022  outa = outa + 1
6023  tmpa(outa) = real(ind)
6024  found = .true.
6025  END IF
6026  END IF
6027  IF (posb_mm.NE.0) THEN
6028  outb = outb + 1
6029  tmpb(outb) = real(posb_mm)
6030  IF (.NOT.found) THEN
6031  outa = outa + 1
6032  tmpa(outa) = real(ind)
6033  found = .true.
6034  END IF
6035  END IF
6036  IF (posb_mp.NE.0) THEN
6037  outb = outb + 1
6038  tmpb(outb) = real(posb_mp)
6039  IF (.NOT.found) THEN
6040  outa = outa + 1
6041  tmpa(outa) = real(ind)
6042  found = .true.
6043  END IF
6044  END IF
6045  IF (posb_pm.NE.0) THEN
6046  outb = outb + 1
6047  tmpb(outb) = real(posb_pm)
6048  IF (.NOT.found) THEN
6049  outa = outa + 1
6050  tmpa(outa) = real(ind)
6051  found = .true.
6052  END IF
6053  END IF
6054  IF (posb_pp.NE.0) THEN
6055  outb = outb + 1
6056  tmpb(outb) = real(posb_pp)
6057  IF (.NOT.found) THEN
6058  outa = outa + 1
6059  tmpa(outa) = real(ind)
6060  found = .true.
6061  END IF
6062  END IF
6063 
6064  END DO
6065  !
6066  !/ Compact indices for wave systems in B.
6067  !/ Check for empty arrays first.
6068  IF (outb.GT.0) THEN
6069  CALL unique(tmpb,outb,dumb,outdumb)
6070  outb = outdumb
6071  END IF
6072  ALLOCATE(indb(outb))
6073  IF (outb.GT.0) indb(1:outb) = int(dumb(1:outb))
6074  IF (ASSOCIATED(dumb)) DEALLOCATE(dumb)
6075  !
6076  !/ Allocate output array and transfer content
6077  !/ for wave systems in A.
6078  ALLOCATE(inda(outa))
6079  IF (outa.GT.0) THEN
6080  ALLOCATE(duma(outa))
6081  duma(:) = 0
6082  CALL qsort(tmpa(1:outa),duma(1:outa),1,outa)
6083  IF (ALLOCATED(duma)) DEALLOCATE(duma)
6084  inda(1:outa) = int(tmpa(1:outa))
6085  END IF
6086  !/
6087  IF (ALLOCATED(tmpa)) DEALLOCATE(tmpa)
6088  IF (ALLOCATED(tmpb)) DEALLOCATE(tmpb)
6089  !/
6090  RETURN
6091  !/

References length(), qsort(), and unique().

Referenced by combinesys().

◆ findnext()

subroutine w3strkmd::findnext ( integer, intent(inout)  i,
integer, intent(inout)  j,
integer, intent(in)  maxI,
integer, intent(in)  maxJ,
character, intent(in)  way,
integer, intent(out)  vertBorder,
integer, intent(out)  horizBorder 
)

Definition at line 2794 of file w3strkmd.F90.

2794  !/
2795  !/ +-----------------------------------+
2796  !/ | WAVEWATCH III NOAA/NCEP |
2797  !/ | H. L. Tolman |
2798  !/ | Jeff Hanson |
2799  !/ | Eve-Marie Devaliere |
2800  !/ | FORTRAN 95 |
2801  !/ | Last update : 4-Jan-2013 |
2802  !/ +-----------------------------------+
2803  !/
2804  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
2805  !/ by Jeff Hanson & Eve-Marie Devaliere
2806  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
2807  !/
2808  !/ Copyright 2009-2013 National Weather Service (NWS),
2809  !/ National Oceanic and Atmospheric Administration. All rights
2810  !/ reserved. WAVEWATCH III is a trademark of the NWS.
2811  !/ No unauthorized use without permission.
2812  !/
2813  IMPLICIT NONE
2814  !
2815  ! 1. Purpose :
2816  !
2817  ! Find next point on spatial search spiral
2818  !
2819  ! 2. Method
2820  !
2821  ! -
2822  !
2823  ! 3. Parameters :
2824  !
2825  ! Parameter list
2826  ! ----------------------------------------------------------------
2827  ! i,j Int in/out Current grid indices
2828  ! maxI, maxJ Int input Maximum indices of wave field
2829  ! way Char input Direction of spiral search
2830  ! vertBorder Int output Flag indicating that vert domain edge has been hit
2831  ! horizBorder Int output Flag indicating that hor domain edge has been hit
2832  !
2833  CHARACTER :: way
2834  INTEGER :: i, j, maxI, maxJ, vertBorder, horizBorder
2835 
2836  INTENT (IN) maxi, maxj, way
2837  INTENT (IN OUT) i, j
2838  INTENT (OUT) vertborder, horizborder
2839  !
2840  ! Local variables
2841  ! ----------------------------------------------------------------
2842  ! -
2843  !
2844  ! 4. Subroutines used :
2845  !
2846  ! Name Type Module Description
2847  ! ----------------------------------------------------------------
2848  ! -
2849  !
2850  ! 5. Subroutines calling
2851  !
2852  ! spiralTrackV3
2853  !
2854  ! 6. Error messages :
2855  !
2856  ! 7. Remarks :
2857  !
2858  ! 8. Structure :
2859  !
2860  ! -
2861  !
2862  ! 9. Switches :
2863  !
2864  ! None defined yet.
2865  !
2866  ! 10. Source code :
2867  !
2868  !/ ------------------------------------------------------------------- /
2869  vertborder=0
2870  horizborder=0
2871  SELECT CASE (way)
2872  CASE ('R')
2873  IF (i.LT.maxi) THEN
2874  i=i+1
2875  ELSE
2876  ! Need to tell findWay that if we hit the border we don't
2877  ! increment stepCount...
2878  horizborder=1
2879  END IF
2880  CASE ('D')
2881  IF (j.GT.1) THEN
2882  j=j-1
2883  ELSE
2884  vertborder=1
2885  END IF
2886  CASE ('L')
2887  IF (i.GT.1) THEN
2888  i=i-1
2889  ELSE
2890  horizborder=1
2891  END IF
2892  CASE ('U')
2893  IF (j.LT.maxj) THEN
2894  j=j+1
2895  ELSE
2896  vertborder=1
2897  END IF
2898  END SELECT
2899 
2900  RETURN

Referenced by spiraltrackv3().

◆ findsys()

subroutine w3strkmd::findsys ( integer, intent(in)  i,
integer, intent(in)  j,
type(dat2d), intent(inout)  wsdat,
integer, intent(inout)  maxSys,
integer, intent(in)  ngbrExt,
integer, intent(in)  maxI,
integer, intent(in)  maxJ,
real, intent(in)  perKnob,
real, intent(in)  dirKnob,
real  hsKnob 
)

Definition at line 2908 of file w3strkmd.F90.

2908  !/
2909  !/ +-----------------------------------+
2910  !/ | WAVEWATCH III NOAA/NCEP |
2911  !/ | A. J. van der Westhuysen |
2912  !/ | Jeff Hanson |
2913  !/ | Eve-Marie Devaliere |
2914  !/ | FORTRAN 95 |
2915  !/ | Last update : 4-Jan-2013 |
2916  !/ +-----------------------------------+
2917  !/
2918  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
2919  !/ by Jeff Hanson & Eve-Marie Devaliere
2920  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
2921  !/
2922  !/ Copyright 2009-2013 National Weather Service (NWS),
2923  !/ National Oceanic and Atmospheric Administration. All rights
2924  !/ reserved. WAVEWATCH III is a trademark of the NWS.
2925  !/ No unauthorized use without permission.
2926  !/
2927  IMPLICIT NONE
2928  !
2929  ! 1. Purpose :
2930  !
2931  ! Find all wave systems that neighbour the grid point (i,j), and
2932  ! match these with the systems at (i,j).
2933  !
2934  ! 2. Method
2935  !
2936  ! For the given point (i,j), find all wave systems at neighbouring grid
2937  ! points within the reach specified by ngbrExt.
2938  !
2939  ! 3. Parameters :
2940  !
2941  ! Parameter list
2942  ! ----------------------------------------------------------------
2943  ! i,j Int input Current grid indices
2944  ! maxI, maxJ Int input Maximum indices of wave field
2945  ! wsdat Type(dat2d) in/out Input data structure to be spiral tracked
2946  ! maxSys Int in/out Maximum number of systems identified
2947  !
2948  TYPE(dat2d) :: wsdat
2949  INTEGER :: i, j, maxI, maxJ, ngbrExt, maxSys
2950  REAL :: perKnob ,dirKnob, hsKnob
2951 
2952  INTENT (IN) i, j, maxi, maxj, ngbrext, perknob ,dirknob
2953  INTENT (IN OUT) wsdat, maxsys
2954  !
2955  ! Local variables
2956  ! ----------------------------------------------------------------
2957  ! tmpsys TYPE(system) Temporary instance of the wave system variable
2958  ! nngbr Int Number of neighbours found
2959  !
2960  TYPE(system), ALLOCATABLE :: tmpsys(:)
2961  TYPE(neighbr) :: ngbr(50)
2962  TYPE(mtchsys) :: match
2963  LOGICAL :: found
2964  INTEGER :: counter, ii, jj, nngbr, startCount, endCount, l,&
2965  nout, maxS, s, p, n, countAll, ind, minInd, &
2966  npart, pp, leng
2967  INTEGER :: allFullSys(50)
2968  REAL, POINTER :: realarr(:)
2969  INTEGER, ALLOCATABLE :: allSys(:)
2970  REAL :: hsAll(50),tpAll(50),dirAll(50),GOF(50)
2971  REAL :: absDir,absPer,absHs,T,&
2972  deltaPer,deltaDir,deltaHs,temp
2973  REAL :: dx, m1, m2
2974  REAL :: GOFMinVal
2975  INTEGER :: GOFMinInd
2976  !
2977  ! 4. Subroutines used :
2978  !
2979  ! Name Type Module Description
2980  ! ----------------------------------------------------------------
2981  ! UNIQUE
2982  ! combinePartitionsV2
2983  !
2984  ! 5. Subroutines calling
2985  !
2986  ! spiralTrackV3
2987  !
2988  ! 6. Error messages :
2989  !
2990  ! 7. Remarks :
2991  !
2992  ! 8. Structure :
2993  !
2994  ! -
2995  !
2996  ! 9. Switches :
2997  !
2998  ! None defined yet.
2999  !
3000  ! 10. Source code :
3001  !
3002  !/ ------------------------------------------------------------------- /
3003  NULLIFY(realarr)
3004  ! WRITE(20,*) 'findSys: i,j,maxSys =',i,j,maxSys
3005 
3006  ! First find the checked neighbor
3007  counter=1
3008  DO ii=(i-ngbrext), (i+ngbrext)
3009  DO jj=(j-ngbrext), (j+ngbrext)
3010  IF ( (ii.GT.0).AND.(jj.GT.0).AND. &
3011  (jj.LE.maxj).AND.(ii.LE.maxi) ) THEN
3012  IF ( wsdat%par(ii,jj)%checked.EQ.1 ) THEN
3013  ngbr(counter)%par = wsdat%par(ii,jj) !Added the par field to maintain the data structure
3014  ngbr(counter)%i = ii
3015  ngbr(counter)%j = jj
3016  counter=counter+1
3017  END IF
3018  END IF
3019  END DO
3020  END DO
3021  ! New variable nngbr
3022  nngbr=counter-1
3023 
3024  IF (nngbr.GT.0) THEN
3025  allfullsys(:) = 0
3026  startcount=1
3027  l=1
3028  DO WHILE (l.LE.nngbr)
3029  leng = length(real(ngbr(l)%par%sys), &
3030  SIZE(ngbr(l)%par%sys),real(9999))
3031  endcount = startcount+leng-1
3032  allfullsys(startcount:endcount) = ngbr(l)%par%sys(1:leng)
3033  startcount=endcount+1
3034  l=l+1
3035  END DO
3036 
3037  IF (endcount.EQ.0) WRITE(20,*) '***1.Calling UNIQUE w. len=0!'
3038  CALL unique (real(allfullsys),endcount,realarr,nout) !Can one do this?
3039  ALLOCATE(allsys(nout))
3040  allsys = int(realarr) !Can one do this?
3041  IF (ASSOCIATED(realarr)) DEALLOCATE(realarr)
3042  maxs = maxval(allsys)
3043 
3044  IF (maxsys.LT.maxs) THEN
3045  maxsys=maxs
3046  END IF
3047  ! Initiate sys num
3048  ALLOCATE( tmpsys(SIZE(allsys)) )
3049  ! Clear the wsdat%par(i,j)%sys field, new values assigned below.
3050  ! System info temporarily stored in allSys
3051  wsdat%par(i,j)%sys(1:10) = 9999
3052 
3053  DO s=1, SIZE(allsys)
3054  hsall(:) = 0.
3055  tpall(:) = 0.
3056  dirall(:) = 0.
3057  ! wfAll(:) = 0.
3058  n=1
3059  countall=0
3060  DO WHILE (n.LE.nngbr)
3061  ! Calculate mean of common neighbor wave system
3062  ! for every neigbor wave system
3063  found = .false.
3064  DO ind = 1, SIZE(ngbr(n)%par%sys) !Optimize this?
3065  IF ( ngbr(n)%par%sys(ind).EQ.allsys(s) ) THEN !Put sys under par to maintain structure
3066  found = .true.
3067  EXIT
3068  END IF
3069  END DO
3070 
3071  IF (found) THEN
3072  countall=countall+1
3073  hsall(countall)=ngbr(n)%par%hs(ind)
3074  tpall(countall)=ngbr(n)%par%tp(ind)
3075  dirall(countall)=ngbr(n)%par%dir(ind)
3076  ! wfAll(countAll)=ngbr(n)%par%wf(ind)
3077  ELSE
3078  n=n+1
3079  cycle
3080  END IF
3081  n=n+1
3082  END DO
3083  tmpsys(s)%hsMean = sum(hsall(1:countall))/countall
3084  tmpsys(s)%tpMean = sum(tpall(1:countall))/countall
3085  tmpsys(s)%dirMean = &
3086  mean_anglev2(dirall(1:countall),countall)
3087  ! tmpsys(s)%wfMean = SUM(wfAll(1:countAll))/countAll
3088  END DO
3089 
3090  ! Find the partition at current (i,j) point that matches previously
3091  ! identified wave systems if any...
3092  wsdat%par(i,j)%ngbrSys(1:SIZE(allsys)) = allsys
3093 
3094  npart = length(real(wsdat%par(i,j)%ipart), &
3095  SIZE(wsdat%par(i,j)%ipart),real(0))
3096  DO p = 1, npart
3097  IF ( (wsdat%par(i,j)%hs(p).LT.hsknob).OR. &
3098  (wsdat%par(i,j)%tp(p).EQ.0.) ) THEN
3099  wsdat%par(i,j)%sys(p)=-1
3100  cycle
3101  END IF
3102 
3103  ind=0 !Replaced 'index' by 'ind'
3104  match%sysVal(:) = 9999
3105  match%tpVal(:) = 9999.
3106  match%dirVal(:) = 9999.
3107  ! match%wfVal(:) = 9999.
3108  ! Cycle through the neighbouring systems identified above
3109  DO s=1,SIZE(allsys)
3110  abshs = abs(wsdat%par(i,j)%hs(p)-tmpsys(s)%hsMean)
3111  absper = abs(wsdat%par(i,j)%tp(p)-tmpsys(s)%tpMean)
3112  absdir = abs(wsdat%par(i,j)%dir(p)-tmpsys(s)%dirMean)
3113  ! absWf = ABS(wsdat%par(i,j)%wf(p)-tmpsys(s)%wfMean)
3114  IF (absdir.GT.180) THEN
3115  absdir = 360 - absdir
3116  IF (absdir.LT.0) THEN
3117  WRITE(20,*) '*** WARNING: absDir negative!'
3118  WRITE(20,*) 'wsdat%par(i,j)%dir(p) =', &
3119  wsdat%par(i,j)%dir(p)
3120  WRITE(20,*) 'tmpsys(s)%dirMean) =', &
3121  tmpsys(s)%dirMean
3122  END IF
3123  END IF
3124  ! Calculate delta dir and freq as a function of the partition
3125  ! dir and freq
3126  t = tmpsys(s)%tpMean
3127  dx = 0.5*( (wsdat%lon(2,1)-wsdat%lon(1,1)) + &
3128  (wsdat%lat(1,2)-wsdat%lat(1,1)) )
3129  m1 = -3.645*t + 63.211
3130  m1 = max(m1,10.)
3131  m2 = -0.346*t + 3.686
3132  m2 = max(m2,0.6)
3133  !1stddev m1 = -2.219*T + 35.734
3134  !1stddev m1 = MAX(m1,5.)
3135  !1stddev m2 = -0.226*T + 2.213
3136  !1stddev m2 = MAX(m2,0.35)
3137  !5stddev m1 = -5.071*T + 90.688
3138  !5stddev m1 = MAX(m1,16.)
3139  !5stddev m2 = -0.467*T + 5.161
3140  !5stddev m2 = MAX(m2,1.0)
3141  deltadir = m1*dx + dirknob
3142  deltaper = m2*dx + perknob
3143  deltahs = 0.25*tmpsys(s)%hsMean
3144  IF ((absper.LT.deltaper).AND.(absdir.LT.deltadir)) THEN
3145  ind=ind+1
3146  match%sysVal(ind) = allsys(s)
3147  match%tpVal(ind) = absper
3148  match%dirVal(ind) = absdir
3149  match%hsVal(ind) = abshs
3150  ! match%wfVal(ind) = absWf
3151  END IF
3152  END DO
3153 
3154  IF (ind.GT.0) THEN
3155  IF (ind.EQ.1) THEN
3156  wsdat%par(i,j)%sys(p) = match%sysVal(1)
3157  ELSE
3158  ! Take the closest match, using GoF function
3159  gof(:) = 9999.
3160  gof(1:ind) = (match%tpVal(1:ind)/deltaper)**2 + &
3161  (match%dirVal(1:ind)/deltadir)**2 + &
3162  (match%hsVal(1:ind)/deltahs)**2
3163  gofminval = minval(gof(1:ind))
3164  gofminind = findfirst(gof(1:ind),ind,gofminval)
3165  wsdat%par(i,j)%sys(p) = match%sysVal(gofminind) !The index of the system is swapped - the remaining info stays the same!
3166  END IF
3167  END IF
3168  END DO
3169  END IF
3170 
3171  ! Now check if 2 partitions have been associated to the same wave system, if
3172  ! so combine them
3173  npart = length(real(wsdat%par(i,j)%ipart), &
3174  SIZE(wsdat%par(i,j)%ipart),real(0))
3175  DO p = 1, (npart-1) !Could probably be optimized!
3176  DO pp = (p+1), npart
3177  IF (wsdat%par(i,j)%sys(p).EQ.wsdat%par(i,j)%sys(pp)) THEN
3178  ! There is at least one duplicate, so combine systems
3179  CALL combinepartitionsv2(wsdat%par(i,j))
3180  END IF
3181  END DO
3182  END DO
3183  ! Now that we have associated any possible partition to an existing
3184  ! wave system, we check if any wave system is free. If so give it a
3185  ! new wave system number
3186  npart = length(real(wsdat%par(i,j)%ipart), &
3187  SIZE(wsdat%par(i,j)%ipart),real(0))
3188 
3189  DO p = 1, npart
3190  IF (wsdat%par(i,j)%sys(p).EQ.9999) THEN
3191  maxsys = maxsys + 1
3192  wsdat%par(i,j)%sys(p) = maxsys
3193  END IF
3194  END DO
3195  wsdat%par(i,j)%checked=1
3196 
3197  IF (ALLOCATED(allsys)) DEALLOCATE(allsys)
3198  IF (ALLOCATED(tmpsys)) DEALLOCATE(tmpsys)
3199 
3200  RETURN

References combinepartitionsv2(), findfirst(), length(), mean_anglev2(), and unique().

Referenced by spiraltrackv3().

◆ findway()

subroutine w3strkmd::findway ( character, intent(inout)  way,
integer  horizStepCount,
integer  vertStepCount,
integer, intent(in)  vertBorder,
integer, intent(in)  horizBorder,
integer, intent(out)  stepCount 
)

Definition at line 2678 of file w3strkmd.F90.

2678  !/
2679  !/ +-----------------------------------+
2680  !/ | WAVEWATCH III NOAA/NCEP |
2681  !/ | A. J. van der Westhuysen |
2682  !/ | Jeff Hanson |
2683  !/ | Eve-Marie Devaliere |
2684  !/ | FORTRAN 95 |
2685  !/ | Last update : 4-Jan-2013 |
2686  !/ +-----------------------------------+
2687  !/
2688  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
2689  !/ by Jeff Hanson & Eve-Marie Devaliere
2690  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
2691  !/
2692  !/ Copyright 2009-2013 National Weather Service (NWS),
2693  !/ National Oceanic and Atmospheric Administration. All rights
2694  !/ reserved. WAVEWATCH III is a trademark of the NWS.
2695  !/ No unauthorized use without permission.
2696  !/
2697  IMPLICIT NONE
2698  !
2699  ! 1. Purpose :
2700  !
2701  ! From the direction (way) we were going before, find which direction we
2702  ! are going now and how many 'steps' we need to take
2703  !
2704  ! 2. Method
2705  !
2706  ! -
2707  !
2708  ! 3. Parameters :
2709  !
2710  ! Parameter list
2711  ! ----------------------------------------------------------------
2712  ! way Char in/out Direction of spiral search
2713  ! vertBorder Int input
2714  ! horizBorder Int input
2715  ! stepCount Int output Number of steps to go in the selected direction (way)
2716  !
2717  CHARACTER :: way *1
2718  INTEGER :: horizStepCount, vertStepCount, &
2719  vertBorder, horizBorder, stepCount
2720 
2721  INTENT (IN) vertborder, horizborder
2722  INTENT (OUT) stepcount
2723  INTENT (IN OUT) way
2724  !
2725  ! Local variables
2726  ! ----------------------------------------------------------------
2727  ! -
2728  !
2729  ! 4. Subroutines used :
2730  !
2731  ! Name Type Module Description
2732  ! ----------------------------------------------------------------
2733  ! -
2734  !
2735  ! 5. Subroutines calling
2736  !
2737  ! spiralTrackV3
2738  !
2739  ! 6. Error messages :
2740  !
2741  ! 7. Remarks :
2742  !
2743  ! 8. Structure :
2744  !
2745  ! See above
2746  !
2747  ! 9. Switches :
2748  !
2749  ! None defined yet.
2750  !
2751  ! 10. Source code :
2752  !
2753  !/ ------------------------------------------------------------------- /
2754  SELECT CASE (way)
2755  CASE ('R')
2756  way='D'
2757  vertstepcount=vertstepcount+1
2758  IF (horizborder.EQ.1) THEN
2759  horizstepcount=horizstepcount-1
2760  END IF
2761  stepcount=vertstepcount
2762  CASE ('D')
2763  way='L'
2764  horizstepcount=horizstepcount+1
2765  IF (vertborder.EQ.1) THEN
2766  vertstepcount=vertstepcount-1
2767  END IF
2768  stepcount=horizstepcount
2769  CASE ('L')
2770  way='U'
2771  vertstepcount=vertstepcount+1
2772  IF (horizborder.EQ.1) THEN
2773  horizstepcount=horizstepcount-1
2774  END IF
2775  stepcount=vertstepcount
2776  CASE ('U')
2777  way='R'
2778  horizstepcount=horizstepcount+1
2779  IF (vertborder.EQ.1) THEN
2780  vertstepcount=vertstepcount-1
2781  END IF
2782  stepcount=horizstepcount
2783  CASE DEFAULT
2784  WRITE(20,*) 'In spaTack:findWay should NOT go here!'
2785  END SELECT
2786 
2787  RETURN

Referenced by spiraltrackv3().

◆ intersect()

subroutine w3strkmd::intersect ( real, dimension(insize1), intent(in)  INARRAY1,
integer, intent(in)  INSIZE1,
real, dimension(insize2), intent(in)  INARRAY2,
integer, intent(in)  INSIZE2,
real, dimension(:), pointer  OUTARRAY,
integer, intent(out)  OUTSIZE,
real, dimension(:), pointer  IND1,
real, dimension(:), pointer  IND2 
)

Definition at line 5096 of file w3strkmd.F90.

5096  !/
5097  !/ +-----------------------------------+
5098  !/ | WAVEWATCH III NOAA/NCEP |
5099  !/ | A. J. van der Westhuysen |
5100  !/ | Jeff Hanson |
5101  !/ | Eve-Marie Devaliere |
5102  !/ | FORTRAN 95 |
5103  !/ | Last update : 20-Dec-2016 |
5104  !/ +-----------------------------------+
5105  !/
5106  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
5107  !/ by Jeff Hanson & Eve-Marie Devaliere
5108  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
5109  !/ 20-Dec-2016 : Add count-histogram method based on
5110  !/ algorithm from Mirko Velic (BoM)
5111  !/ (S. Zieger BoM, Australia) ( version 5.16 )
5112  !/
5113  !/ Copyright 2009-2013 National Weather Service (NWS),
5114  !/ National Oceanic and Atmospheric Administration. All rights
5115  !/ reserved. WAVEWATCH III is a trademark of the NWS.
5116  !/ No unauthorized use without permission.
5117  !/
5118  IMPLICIT NONE
5119  !
5120  ! 1. Purpose :
5121  !
5122  ! (i) Returns the elements that are mutual in INARRAY1 and INARRAY2.
5123  ! (ii) Sort the resulting array in ascending order.
5124  !
5125  ! 2. Method
5126  !
5127  ! Sort with counting/histogram method with input array being
5128  ! cast as integer.
5129  !
5130  ! 3. Parameters :
5131  !
5132  ! Parameter list
5133  ! ----------------------------------------------------------------
5134  ! INARRAY1 REAL ARR input Input array
5135  ! INSIZE1 INTEGER input Size of input array
5136  ! INARRAY2 REAL ARR input Input array
5137  ! INSIZE2 INTEGER input Size of input array
5138  ! OUTARRAY REAL ARR output Output array
5139  ! OUTSIZE INTEGER output Size of output array (number of
5140  ! intersects)
5141  !
5142  INTEGER :: INSIZE1, INSIZE2, OUTSIZE
5143  REAL :: INARRAY1(INSIZE1), INARRAY2(INSIZE2)
5144  REAL, POINTER :: OUTARRAY(:)
5145  REAL, POINTER :: IND1(:), IND2(:)
5146  !
5147  INTENT (IN) inarray1, insize1, inarray2, insize2
5148  INTENT (OUT) outsize
5149  !
5150  ! Local variables
5151  ! ----------------------------------------------------------------
5152  ! VIDX1, VIDX2 - array(s) in which the value is represented by
5153  ! its index (i.e. histogram with frequency 1)
5154  ! N - data range and size of possible intersections.
5155  !
5156  LOGICAL,ALLOCATABLE :: VIDX1(:),VIDX2(:)
5157  INTEGER,ALLOCATABLE :: IPOS1(:),IPOS2(:)
5158  !
5159  INTEGER :: I, J
5160  INTEGER :: N, IMIN, IMAX
5161  INTEGER :: MINV1,MAXV1, MINV2, MAXV2
5162  !
5163  ! 4. Subroutines used :
5164  !
5165  ! Name Type Scope Description
5166  ! ----------------------------------------------------------------
5167  !
5168  ! 5. Subroutines calling
5169  !
5170  ! 6. Error messages :
5171  !
5172  ! 7. Remarks :
5173  !
5174  ! 8. Structure :
5175  !
5176  ! -
5177  !
5178  ! 9. Switches :
5179  !
5180  ! None defined yet.
5181  !
5182  ! 10. Source code :
5183  !
5184  !/ ------------------------------------------------------------------- /
5185  !
5186  outsize = 0
5187 
5188  !/ --- Calculate the range of the two sets. ---
5189  minv1 = int(minval(inarray1))
5190  maxv1 = int(maxval(inarray1))
5191  minv2 = int(minval(inarray2))
5192  maxv2 = int(maxval(inarray2))
5193 
5194  !/ --- Check if ranges overlap. ---
5195  IF ( maxv1.LT.minv2.OR.insize1.EQ.0.OR.insize2.EQ.0 ) THEN
5196  ALLOCATE(outarray(outsize))
5197  ALLOCATE(ind1(outsize))
5198  ALLOCATE(ind2(outsize))
5199  ELSE
5200  !/ --- Calculate size of temporary output arrays. Allow
5201  !/ extra elements: ZERO, and make sure index is 1:N. ---
5202  imin = min(minv1,minv2)-1
5203  imax = max(maxv1,maxv2)+1
5204 
5205  n = imax-imin
5206 
5207  ALLOCATE(vidx1(n),vidx2(n))
5208  ALLOCATE(ipos1(n),ipos2(n))
5209 
5210  vidx1(1:n) = .false.
5211  vidx2(1:n) = .false.
5212 
5213  DO i=1,insize1
5214  j = int(inarray1(i)-imin)
5215  vidx1(j) = .true.
5216  ipos1(j) = i
5217  END DO
5218 
5219  DO i=1,insize2
5220  j = int(inarray2(i)-imin)
5221  !/ --- Intersect arrays and check for
5222  !/ duplicate elements in array2. ---
5223  IF ( vidx1(j).AND..NOT.vidx2(j) ) THEN
5224  outsize = outsize + 1
5225  vidx2(j) = .true.
5226  ipos2(j) = i
5227  END IF
5228  END DO
5229  !/ --- Allocate output arrays. ---
5230  ALLOCATE(outarray(outsize))
5231  ALLOCATE(ind1(outsize))
5232  ALLOCATE(ind2(outsize))
5233  !/ --- Transfer contents. ---
5234  i = 1
5235  DO j=1,n
5236  IF ( vidx1(j).AND.vidx2(j).AND.i.LE.outsize ) THEN
5237  outarray(i) = inarray1(ipos1(j))
5238  ind1(i) = ipos1(j)
5239  ind2(i) = ipos2(j)
5240  i = i + 1
5241  END IF
5242  END DO
5243  !/ --- Free memory. ---
5244  DEALLOCATE(vidx1,vidx2)
5245  DEALLOCATE(ipos1,ipos2)
5246  END IF
5247  !/
5248  RETURN
5249  !/

Referenced by timetrackingv2().

◆ length()

integer function w3strkmd::length ( real, dimension(arrsize)  ARRAY,
integer  ARRSIZE,
real  VAL 
)

Definition at line 5432 of file w3strkmd.F90.

5432  !/
5433  !/ +-----------------------------------+
5434  !/ | WAVEWATCH III NOAA/NCEP |
5435  !/ | A. J. van der Westhuysen |
5436  !/ | Jeff Hanson |
5437  !/ | Eve-Marie Devaliere |
5438  !/ | FORTRAN 95 |
5439  !/ | Last update : 4-Jan-2013 |
5440  !/ +-----------------------------------+
5441  !/
5442  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
5443  !/ by Jeff Hanson & Eve-Marie Devaliere
5444  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
5445  !/
5446  !/ Copyright 2009-2013 National Weather Service (NWS),
5447  !/ National Oceanic and Atmospheric Administration. All rights
5448  !/ reserved. WAVEWATCH III is a trademark of the NWS.
5449  !/ No unauthorized use without permission.
5450  !/
5451  IMPLICIT NONE
5452  !
5453  ! 1. Purpose :
5454  !
5455  ! Find largest index in ARRAY with a value not equal to the
5456  ! filler value VAL.
5457  ! E.g. If VAL = 9999. and ARRAY = [X X X X 9999. 9999. 9999.],
5458  ! the function returns 4.
5459  !
5460  ! 3. Parameters :
5461  !
5462  ! Parameter list
5463  ! ----------------------------------------------------------------
5464  INTEGER :: ARRSIZE
5465  REAL :: ARRAY(ARRSIZE)
5466  REAL :: VAL
5467  !
5468  ! Local variables
5469  ! ----------------------------------------------------------------
5470  REAL :: FIELD
5471  INTEGER :: I
5472  !
5473  ! 10. Source code :
5474  !
5475  !/ ------------------------------------------------------------------- /
5476  IF (arrsize.GT.0) THEN
5477  i = 1
5478  field = array(i)
5479  DO WHILE (field.NE.val)
5480  i = i+1
5481  IF (i.GT.SIZE(array)) EXIT
5482  field = array(i)
5483  END DO
5484  length = i-1
5485  ELSE
5486  length = 0
5487  END IF
5488 
5489  RETURN

Referenced by combinepartitionsv2(), combinesys(), combinewavesystems(), findijv4(), findsys(), printfinalsys(), spiraltrackv3(), and timetrackingv2().

◆ mean_anglev2()

real function w3strkmd::mean_anglev2 ( real, dimension(ll)  ang,
integer  ll 
)

Definition at line 4463 of file w3strkmd.F90.

4463  !/
4464  !/ +-----------------------------------+
4465  !/ | WAVEWATCH III NOAA/NCEP |
4466  !/ | A. J. van der Westhuysen |
4467  !/ | Jeff Hanson |
4468  !/ | Eve-Marie Devaliere |
4469  !/ | FORTRAN 95 |
4470  !/ | Last update : 4-Jan-2013 |
4471  !/ +-----------------------------------+
4472  !/
4473  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
4474  !/ by Jeff Hanson & Eve-Marie Devaliere
4475  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
4476  !/
4477  !/ Copyright 2009-2013 National Weather Service (NWS),
4478  !/ National Oceanic and Atmospheric Administration. All rights
4479  !/ reserved. WAVEWATCH III is a trademark of the NWS.
4480  !/ No unauthorized use without permission.
4481  !/
4482  IMPLICIT NONE
4483  !
4484  ! 1. Purpose :
4485  !
4486  ! Compute the mean direction from array of directions
4487  !
4488  ! 2. Method
4489  !
4490  ! ang is a column vector of angles
4491  ! m_ang is the mean from a unit-vector average of ang
4492  ! Assumes clockwise rotation from North = 0.
4493  !
4494  ! 3. Parameters :
4495  !
4496  ! Parameter list
4497  ! ----------------------------------------------------------------
4498  ! ang Real input Array of angles to average
4499  ! ll Int input Length of ang
4500  !
4501  REAL :: ang(ll)
4502  INTEGER :: ll
4503  !
4504  ! Local variables
4505  ! ----------------------------------------------------------------
4506  ! u,v Real Arrays of u,v dir components to average
4507  ! um,vm Real Mean u,v dir components
4508  ! theta Real Mean direction relative to North
4509  !
4510  REAL :: PI
4511  parameter(pi = 3.1416)
4512  REAL :: u(ll), v(ll), vm, um, theta
4513  !
4514  ! 4. Subroutines used :
4515  !
4516  ! Name Type Module Description
4517  ! ----------------------------------------------------------------
4518  ! -
4519  !
4520  ! 5. Subroutines calling
4521  !
4522  ! findSys
4523  !
4524  ! 6. Error messages :
4525  !
4526  ! 7. Remarks :
4527  !
4528  ! 8. Structure :
4529  !
4530  ! -
4531  !
4532  ! 9. Switches :
4533  !
4534  ! None defined yet.
4535  !
4536  ! 10. Source code :
4537  !
4538  !/ ------------------------------------------------------------------- /
4539 
4540  ! North and East components
4541  v(:) = cos(ang(:)*(pi/180.))
4542  u(:) = sin(ang(:)*(pi/180.))
4543  vm = sum(v)/ll
4544  um = sum(u)/ll
4545 
4546  ! Compute mean magnitude and direction relative to North (from Upolar.m)
4547  theta = (atan2(um,vm))*(180/pi)
4548 
4549  ! Convert inputs to radians, the to the -pi to pi range
4550  ! (incorporated from original function xunwrapV2.m)
4551 
4552  ! Convert to radians
4553  theta = theta*(pi/180)
4554 
4555  theta = pi*((abs(theta)/pi) - &
4556  2*ceiling(((abs(theta)/pi)-1)/2))*sign(1.,theta)
4557 
4558  ! Shift the points in the -pi to 0 range to the pi to 2pi range
4559  IF (theta.LT.0.) theta = theta + 2*pi
4560 
4561  ! Convert back to degrees and return value
4562  mean_anglev2 = theta*(180/pi)
4563 
4564  RETURN

References constants::pi.

Referenced by combinesys(), findsys(), and printfinalsys().

◆ mean_anglev3()

real function w3strkmd::mean_anglev3 ( real, dimension(ll)  ang,
real, dimension(ll)  hsign,
integer  ll 
)

Definition at line 4570 of file w3strkmd.F90.

4570  !/
4571  !/ +-----------------------------------+
4572  !/ | WAVEWATCH III NOAA/NCEP |
4573  !/ | A. J. van der Westhuysen |
4574  !/ | Jeff Hanson |
4575  !/ | Eve-Marie Devaliere |
4576  !/ | FORTRAN 95 |
4577  !/ | Last update : 4-Jan-2013 |
4578  !/ +-----------------------------------+
4579  !/
4580  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
4581  !/ by Jeff Hanson & Eve-Marie Devaliere
4582  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
4583  !/
4584  !/ Copyright 2009-2013 National Weather Service (NWS),
4585  !/ National Oceanic and Atmospheric Administration. All rights
4586  !/ reserved. WAVEWATCH III is a trademark of the NWS.
4587  !/ No unauthorized use without permission.
4588  !/
4589  IMPLICIT NONE
4590  !
4591  ! 1. Purpose :
4592  !
4593  ! Compute the mean direction from array of directions,
4594  ! INCLUDING WEIGHTING WITH HMO
4595  !
4596  ! 2. Method
4597  !
4598  ! ang is a column vector of angles
4599  ! m_ang is the mean from a unit-vector average of ang
4600  ! Assumes clockwise rotation from North = 0.
4601  !
4602  ! 3. Parameters :
4603  !
4604  ! Parameter list
4605  ! ----------------------------------------------------------------
4606  ! ang Real input Array of angles to average
4607  ! ll Int input Length of ang
4608  !
4609  REAL :: ang(ll), hsign(ll)
4610  REAL :: TEMP1, TEMP2
4611  INTEGER :: ll
4612  !
4613  ! Local variables
4614  ! ----------------------------------------------------------------
4615  ! u,v Real Arrays of u,v dir components to average
4616  ! um,vm Real Mean u,v dir components
4617  ! theta Real Mean direction relative to North
4618  !
4619  REAL :: PI
4620  parameter(pi = 3.1416)
4621  REAL :: u(ll), v(ll), vm, um, theta
4622  INTEGER :: i
4623  !
4624  ! 4. Subroutines used :
4625  !
4626  ! Name Type Module Description
4627  ! ----------------------------------------------------------------
4628  ! -
4629  !
4630  ! 5. Subroutines calling
4631  !
4632  ! findSys
4633  !
4634  ! 6. Error messages :
4635  !
4636  ! 7. Remarks :
4637  !
4638  ! 8. Structure :
4639  !
4640  ! -
4641  !
4642  ! 9. Switches :
4643  !
4644  ! None defined yet.
4645  !
4646  ! 10. Source code :
4647  !
4648  !/ ------------------------------------------------------------------- /
4649 
4650  ! North and East components
4651  v(:) = cos(ang(:)*(pi/180.))
4652  u(:) = sin(ang(:)*(pi/180.))
4653  temp1 = 0.
4654  temp2 = 0.
4655  DO i = 1,ll
4656  temp1 = temp1 + (hsign(i)**2)*v(i)
4657  temp2 = temp2 + (hsign(i)**2)*u(i)
4658  END DO
4659  vm = temp1/max(sum(hsign**2),0.001)
4660  um = temp2/max(sum(hsign**2),0.001)
4661 
4662  ! Compute mean magnitude and direction relative to North (from Upolar.m)
4663  theta = (atan2(um,vm))*(180/pi)
4664 
4665  ! Convert inputs to radians, the to the -pi to pi range
4666  ! (incorporated from original function xunwrapV2.m)
4667 
4668  ! Convert to radians
4669  theta = theta*(pi/180)
4670 
4671  theta = pi*((abs(theta)/pi) - &
4672  2*ceiling(((abs(theta)/pi)-1)/2))*sign(1.,theta)
4673 
4674  ! Shift the points in the -pi to 0 range to the pi to 2pi range
4675  IF (theta.LT.0.) theta = theta + 2*pi
4676 
4677  ! Convert back to degrees and return value
4678  mean_anglev3 = theta*(180/pi)
4679 
4680  RETURN

References constants::pi.

Referenced by combinesys(), and printfinalsys().

◆ printfinalsys()

subroutine w3strkmd::printfinalsys ( type(dat2d), intent(in)  wsdat,
integer, intent(out)  maxSys,
integer, dimension(:), intent(in), allocatable  actSysInd,
integer, intent(in)  maxI,
integer, intent(in)  maxJ,
integer, intent(in)  flag,
type(system), dimension(:), pointer  sys 
)

Definition at line 3455 of file w3strkmd.F90.

3455  !/
3456  !/ +-----------------------------------+
3457  !/ | WAVEWATCH III NOAA/NCEP |
3458  !/ | A. J. van der Westhuysen |
3459  !/ | Jeff Hanson |
3460  !/ | Eve-Marie Devaliere |
3461  !/ | FORTRAN 95 |
3462  !/ | Last update : 4-Jan-2013 |
3463  !/ +-----------------------------------+
3464  !/
3465  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
3466  !/ by Jeff Hanson & Eve-Marie Devaliere
3467  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
3468  !/
3469  !/ Copyright 2009-2013 National Weather Service (NWS),
3470  !/ National Oceanic and Atmospheric Administration. All rights
3471  !/ reserved. WAVEWATCH III is a trademark of the NWS.
3472  !/ No unauthorized use without permission.
3473  !/
3474  IMPLICIT NONE
3475  !
3476  ! 1. Purpose :
3477  !
3478  ! Output (print) the final output systems for this time step.
3479  !
3480  ! 2. Method
3481  !
3482  ! -
3483  !
3484  ! 3. Parameters :
3485  !
3486  ! Parameter list
3487  ! ----------------------------------------------------------------
3488  ! wsdat Type(dat2d) input Combined data structure
3489  ! maxI, maxJ Int input Maximum indices of wave field
3490  ! maxSys Int input Maximum number of systems identified
3491  ! flag Int input Flag for printing system
3492  ! sys Type(system) output Final set of tracked systems, for one time level
3493  !
3494  TYPE(dat2d) :: wsdat
3495  TYPE(system), POINTER :: sys(:)
3496  INTEGER :: maxSys, maxI, maxJ, flag
3497  INTEGER, ALLOCATABLE :: actSysInd(:)
3498 
3499  INTENT (IN) wsdat, actsysind, maxi, maxj, flag
3500  INTENT (OUT) maxsys
3501  ! INTENT (IN OUT) sys
3502  !
3503  ! Local variables
3504  ! ----------------------------------------------------------------
3505  ! ic Int Counter for wave systems
3506  !
3507  INTEGER :: ic, nGuys, startInd, endInd, i, j, ind, leng, leng2
3508  INTEGER :: UNISIZE, DIFSIZE
3509  REAL, ALLOCATABLE :: sysOrdered(:)
3510  REAL, POINTER :: UNIARR(:), DIFARR(:)
3511  INTEGER, ALLOCATABLE :: ngbrSysAll(:), sysSortedInd(:)
3512  REAL :: TEMP(2), TEMP1, TEMP2
3513  !
3514  ! 4. Subroutines used :
3515  !
3516  ! Name Type Module Description
3517  ! ----------------------------------------------------------------
3518  ! UNIQUE
3519  ! SETDIFF
3520  ! SORT
3521  !
3522  ! 5. Subroutines calling
3523  !
3524  ! combineWaveSystems
3525  !
3526  ! 6. Error messages :
3527  !
3528  ! 7. Remarks :
3529  !
3530  ! 8. Structure :
3531  !
3532  ! -
3533  !
3534  ! 9. Switches :
3535  !
3536  ! None defined yet.
3537  !
3538  ! 10. Source code :
3539  !
3540  !/ ------------------------------------------------------------------- /
3541 
3542  ! Initialize sys structure
3543  IF (flag.NE.2) THEN
3544  ! Allocate data structure with the final wave systems
3545  WRITE(20,*) 'In printFinalSys...'
3546  maxsys = SIZE(actsysind)
3547  NULLIFY(sys)
3548  ALLOCATE( sys(maxsys) )
3549  WRITE(20,*) 'Allocated sys okay, SIZE(sys) =',SIZE(sys)
3550 
3551  ALLOCATE( ngbrsysall(50*maxi*maxj) ) !Large enough?
3552  DO ic = 1, maxsys
3553  NULLIFY( sys(ic)%hs )
3554  NULLIFY( sys(ic)%tp )
3555  NULLIFY( sys(ic)%dir )
3556  NULLIFY( sys(ic)%dspr )
3557  ! NULLIFY( sys(ic)%wf )
3558  NULLIFY( sys(ic)%i )
3559  NULLIFY( sys(ic)%j )
3560  NULLIFY( sys(ic)%lat )
3561  NULLIFY( sys(ic)%lon )
3562  ALLOCATE( sys(ic)%hs(maxi*maxj) )
3563  ALLOCATE( sys(ic)%tp(maxi*maxj) )
3564  ALLOCATE( sys(ic)%dir(maxi*maxj) )
3565  ALLOCATE( sys(ic)%dspr(maxi*maxj) )
3566  ! ALLOCATE( sys(ic)%wf(maxI*maxJ) )
3567  ALLOCATE( sys(ic)%i(maxi*maxj) )
3568  ALLOCATE( sys(ic)%j(maxi*maxj) )
3569  ALLOCATE( sys(ic)%lat(maxi*maxj) )
3570  ALLOCATE( sys(ic)%lon(maxi*maxj) )
3571  sys(ic)%hs(:) = 9999. !Optimize this further?
3572  sys(ic)%tp(:) = 9999.
3573  sys(ic)%dir(:) = 9999.
3574  sys(ic)%dspr(:) = 9999.
3575  ! sys(ic)%wf(:) = 9999.
3576  sys(ic)%i(:) = 9999
3577  sys(ic)%j(:) = 9999
3578  sys(ic)%lat(:) = 9999.
3579  sys(ic)%lon(:) = 9999.
3580  sys(ic)%sysInd = 9999
3581  sys(ic)%hsMean = 9999.
3582  sys(ic)%tpMean = 9999.
3583  sys(ic)%dirMean = 9999.
3584  sys(ic)%nPoints = 0
3585  sys(ic)%ngbr(:) = 9999
3586  sys(ic)%grp = 9999
3587  ngbrsysall(:) = 0
3588  startind=1
3589  nguys=0
3590 
3591  DO i = 1, maxi
3592  DO j = 1, maxj
3593  ! ind=wsdat.par(i,j).sys==ic;
3594  DO ind = 1, SIZE(wsdat%par(i,j)%sys) !40.81 !Optimize this?
3595  IF (wsdat%par(i,j)%sys(ind).EQ.actsysind(ic)) &
3596  THEN
3597  nguys=nguys+1
3598  sys(ic)%hs(nguys)=wsdat%par(i,j)%hs(ind)
3599  sys(ic)%tp(nguys)=wsdat%par(i,j)%tp(ind)
3600  sys(ic)%dir(nguys)=wsdat%par(i,j)%dir(ind)
3601  sys(ic)%dspr(nguys)=wsdat%par(i,j)%dspr(ind)
3602  ! sys(ic)%wf(nGuys)=wsdat%par(i,j)%wf(ind)
3603  sys(ic)%i(nguys)=i
3604  sys(ic)%j(nguys)=j
3605  sys(ic)%lat(nguys)=wsdat%lat(i,j)
3606  sys(ic)%lon(nguys)=wsdat%lon(i,j)
3607  leng = length(real(wsdat%par(i,j)%ngbrSys), &
3608  SIZE(wsdat%par(i,j)%ngbrSys),real(9999))
3609  endind = startind + leng-1
3610  ngbrsysall(startind:endind) = &
3611  wsdat%par(i,j)%ngbrSys(1:leng)
3612  startind=endind+1
3613  END IF
3614  END DO
3615  END DO
3616  END DO
3617 
3618  ! if ~isempty(sys)
3619  IF (nguys.GT.0) THEN
3620  sys(ic)%sysInd=ic
3621  sys(ic)%hsMean = sum(sys(ic)%hs(1:nguys))/nguys
3622  sys(ic)%tpMean = sum(sys(ic)%tp(1:nguys))/nguys
3623  ! sys(ic)%dirMean=mean_angle_single(sys(ic).dir) 40.81 Replaced with two-argument mean_angleV2
3624  sys(ic)%dirMean = &
3625  mean_anglev2(sys(ic)%dir(1:nguys),nguys)
3626  !070512----------- Weight averages with Hm0 ---------------------
3627  temp1 = 0.
3628  temp2 = 0.
3629  DO i = 1,nguys
3630  temp1 = temp1 + (sys(ic)%hs(i)**2)*sys(ic)%hs(i)
3631  temp2 = temp2 + (sys(ic)%hs(i)**2)*sys(ic)%tp(i)
3632  END DO
3633  sys(ic)%hsMean = &
3634  temp1/max(sum(sys(ic)%hs(1:nguys)**2),0.001)
3635  sys(ic)%tpMean = &
3636  temp2/max(sum(sys(ic)%hs(1:nguys)**2),0.001)
3637  sys(ic)%dirMean = mean_anglev3(sys(ic)%dir(1:nguys), &
3638  sys(ic)%hs(1:nguys),nguys)
3639  !070512----------- Weight averages with Hm0 ---------------------
3640  sys(ic)%nPoints = nguys
3641  IF (endind.GT.0) THEN
3642  CALL unique(real(ngbrsysall(1:endind)),endind, &
3643  uniarr,unisize)
3644  temp = (/real(sys(ic)%sysInd),real(sys(ic)%sysInd)/)
3645  CALL setdiff(real(uniarr),unisize, &
3646  temp,2,difarr,difsize)
3647  difsize = min(difsize,SIZE(sys(ic)%ngbr))
3648  sys(ic)%ngbr(1:difsize) = nint(difarr(1:difsize))
3649  IF (ASSOCIATED(uniarr)) DEALLOCATE(uniarr)
3650  IF (ASSOCIATED(difarr)) DEALLOCATE(difarr)
3651  END IF
3652  ELSE
3653  cycle
3654  END IF
3655  END DO
3656  IF (ALLOCATED(ngbrsysall)) DEALLOCATE(ngbrsysall)
3657  END IF
3658 
3659  ! Print the sorted field to the screen
3660  leng = length(real(sys(:)%nPoints), &
3661  SIZE(sys(:)%nPoints),real(9999))
3662  ALLOCATE( sysordered(leng) )
3663  ALLOCATE( syssortedind(leng) )
3664  CALL sort (real(sys(:)%nPoints),leng, &
3665  sysordered,syssortedind,'D')
3666  leng = length(real(sysordered), &
3667  SIZE(sysordered),real(0))
3668 
3669  DO ic = 1, leng
3670  leng2 = length(real(sys(syssortedind(ic))%ngbr), &
3671  SIZE(sys(syssortedind(ic))%ngbr),real(9999))
3672  END DO
3673  IF (ALLOCATED(sysordered)) DEALLOCATE(sysordered)
3674  IF (ALLOCATED(syssortedind)) DEALLOCATE(syssortedind)
3675 
3676  RETURN

References length(), mean_anglev2(), mean_anglev3(), setdiff(), sort(), and unique().

Referenced by combinewavesystems().

◆ qsort()

recursive subroutine w3strkmd::qsort ( real, dimension(:), intent(inout)  ARRAY,
real, dimension(:), intent(inout)  IDX,
integer, intent(in)  LO,
integer, intent(in)  HI 
)

Definition at line 5608 of file w3strkmd.F90.

5608  !/
5609  !/ +-----------------------------------+
5610  !/ | WAVEWATCH III NOAA/NCEP |
5611  !/ | Stefan Zieger |
5612  !/ | FORTRAN 95 |
5613  !/ | Last update : 6-Sep-2016 |
5614  !/ +-----------------------------------+
5615  !/
5616  !/ 06-Sep-2016 : Origination, based on code by Mirko ( version 5.16 )
5617  !/ Velic (BoM, Australia)
5618  !/
5619  !/ Copyright 2009-2013 National Weather Service (NWS),
5620  !/ National Oceanic and Atmospheric Administration. All rights
5621  !/ reserved. WAVEWATCH III is a trademark of the NWS.
5622  !/ No unauthorized use without permission.
5623  !/
5624  !
5625  ! 1. Purpose :
5626  !
5627  ! Quicksort algorithm.
5628  !
5629  ! 2. Method
5630  !
5631  ! 3. Parameters :
5632  !
5633  ! Parameter list
5634  ! ----------------------------------------------------------------
5635  ! ARRAY REAL ARR in/out Input array
5636  ! IDX REAL ARR in/out Original indices of input array
5637  ! LO INTEGER input First element
5638  ! HI INTEGER input Last element
5639  !
5640  IMPLICIT NONE
5641  !/
5642  INTEGER, INTENT(IN) :: LO,HI
5643  REAL,INTENT(INOUT) :: ARRAY(:),IDX(:)
5644  !/
5645  ! Local variables
5646  ! ----------------------------------------------------------------
5647  LOGICAL :: LOOP
5648  INTEGER :: TOP, BOT
5649  REAL :: VAL, TMP
5650  !
5651  ! 4. Subroutines used :
5652  !
5653  ! Name Type Scope Description
5654  ! ----------------------------------------------------------------
5655  !
5656  ! 5. Subroutines calling
5657  !
5658  ! 6. Error messages :
5659  !
5660  ! 7. Remarks :
5661  !
5662  ! 8. Structure :
5663  !
5664  ! 9. Switches :
5665  !
5666  ! 10. Source code :
5667  !
5668  !/ ------------------------------------------------------------------- /
5669  !
5670  !/ --- Check array size and bounds. ---
5671  IF ( SIZE(array).EQ. 0 ) THEN
5672  WRITE(6,199)
5673  CALL abort
5674  ELSE IF ( SIZE(array).NE.SIZE(idx) ) THEN
5675  WRITE(6,201)
5676  CALL abort
5677  ELSE IF ( lbound(array,1).GT.lo ) THEN
5678  WRITE(6,203)
5679  CALL abort
5680  ELSE IF ( ubound(array,1).LT.hi ) THEN
5681  WRITE(6,205)
5682  CALL abort
5683  END IF
5684  !
5685  top = lo
5686  bot = hi
5687  val = array(int((lo+hi)/2))
5688  !
5689  loop = .true.
5690  DO WHILE ( loop )
5691  DO WHILE ( array(top).LT.val )
5692  top = top + 1
5693  END DO
5694  DO WHILE ( val.LT.array(bot) )
5695  bot = bot - 1
5696  END DO
5697  IF ( top.LT.bot ) THEN
5698  !/ --- Swap values at indices TOP and BOT ---
5699  tmp = array(top)
5700  array(top) = array(bot)
5701  array(bot) = tmp
5702  !/ --- Swap index values at indices TOP and BOT ---
5703  tmp = idx(top)
5704  idx(top) = idx(bot)
5705  idx(bot) = tmp
5706  !
5707  top = top + 1
5708  bot = bot - 1
5709  ELSE
5710  loop = .false.
5711  END IF
5712 
5713  END DO
5714 
5715  !/ --- Recursive call quicksort ---
5716  IF (lo.LT.top-1) CALL qsort(array,idx,lo,top-1)
5717  IF (bot+1.LT.hi) CALL qsort(array,idx,bot+1,hi)
5718  !
5719  RETURN
5720  !/
5721 199 FORMAT (/' *** WAVEWATCH III ERROR IN W3SYSTRK : '/ &
5722  ' QSORT ARRAY IS EMPTY' )
5723 201 FORMAT (/' *** WAVEWATCH III ERROR IN W3SYSTRK : '/ &
5724  ' QSORT ARRAY SIZE AND INDEX ARRAY SIZE MISMATCH' )
5725 203 FORMAT (/' *** WAVEWATCH III ERROR IN W3SYSTRK : '/ &
5726  ' QSORT ARRAY INDEX OUT OF LOWER BOUND' )
5727 205 FORMAT (/' *** WAVEWATCH III ERROR IN W3SYSTRK : '/ &
5728  ' QSORT ARRAY INDEX OUT OF UPPER BOUND' )
5729  !/

Referenced by findijv4(), setdiff(), sort(), union(), and unique().

◆ qsort_desc()

recursive subroutine w3strkmd::qsort_desc ( real, dimension(:), intent(inout)  ARRAY,
real, dimension(:), intent(inout)  IDX,
integer, intent(in)  LO,
integer, intent(in)  HI 
)

Definition at line 5734 of file w3strkmd.F90.

5734  !/
5735  !/ +-----------------------------------+
5736  !/ | WAVEWATCH III NOAA/NCEP |
5737  !/ | Stefan Zieger |
5738  !/ | FORTRAN 95 |
5739  !/ | Last update : 6-Sep-2016 |
5740  !/ +-----------------------------------+
5741  !/
5742  !/ 06-Sep-2016 : Origination, based on code by Mirko ( version 5.16 )
5743  !/ Velic (BoM, AUstralia)
5744  !/
5745  !/ Copyright 2009-2013 National Weather Service (NWS),
5746  !/ National Oceanic and Atmospheric Administration. All rights
5747  !/ reserved. WAVEWATCH III is a trademark of the NWS.
5748  !/ No unauthorized use without permission.
5749  !/
5750  !
5751  ! 1. Purpose :
5752  !
5753  ! Quicksort algorithm with descending sort order.
5754  !
5755  ! 2. Method
5756  !
5757  ! 3. Parameters :
5758  !
5759  ! Parameter list
5760  ! ----------------------------------------------------------------
5761  ! ARRAY REAL ARR in/out Input array
5762  ! LO INTEGER input First element
5763  ! HI INTEGER input Last element
5764  !
5765  IMPLICIT NONE
5766  !/
5767  INTEGER, INTENT(IN) :: LO,HI
5768  REAL,INTENT(INOUT) :: ARRAY(:),IDX(:)
5769  !/
5770  ! Local variables
5771  ! ----------------------------------------------------------------
5772  INTEGER :: TOP, BOT, I
5773  REAL :: VAL, TMP
5774  LOGICAL :: LOOP
5775  !
5776  ! 4. Subroutines used :
5777  !
5778  ! Name Type Scope Description
5779  ! ----------------------------------------------------------------
5780  !
5781  ! 5. Subroutines calling
5782  !
5783  ! 6. Error messages :
5784  !
5785  ! 7. Remarks :
5786  !
5787  ! 8. Structure :
5788  !
5789  ! 9. Switches :
5790  !
5791  ! 10. Source code :
5792  !
5793  !/ ------------------------------------------------------------------- /
5794  !
5795  !/ --- Check array size and bounds. ---
5796  IF ( SIZE(array).EQ. 0 ) THEN
5797  WRITE(6,199)
5798  CALL abort
5799  ELSE IF ( SIZE(array).NE.SIZE(idx) ) THEN
5800  WRITE(6,201)
5801  CALL abort
5802  ELSE IF ( lbound(array,1).GT.lo ) THEN
5803  WRITE(6,203)
5804  CALL abort
5805  ELSE IF ( ubound(array,1).LT.hi ) THEN
5806  WRITE(6,205)
5807  CALL abort
5808  END IF
5809  !
5810  top = lo
5811  bot = hi
5812  val = array(int((lo+hi)/2))
5813  !
5814  loop = .true.
5815  DO WHILE ( loop )
5816  DO WHILE ( array(top).GT.val )
5817  top = top + 1
5818  END DO
5819  DO WHILE ( val.GT.array(bot) )
5820  bot = bot - 1
5821  END DO
5822  IF ( top.LT.bot ) THEN
5823  !/ --- Swap values at indices TOP and BOT ---
5824  tmp = array(top)
5825  array(top) = array(bot)
5826  array(bot) = tmp
5827  !/ --- Swap index values at indices TOP and BOT ---
5828  tmp = idx(top)
5829  idx(top) = idx(bot)
5830  idx(bot) = tmp
5831  !
5832  top = top + 1
5833  bot = bot - 1
5834  ELSE
5835  loop = .false.
5836  END IF
5837 
5838  END DO
5839  !/ --- Recursive call quicksort ---
5840  IF (lo.LT.top-1) CALL qsort_desc(array,idx,lo,top-1)
5841  IF (bot+1.LT.hi) CALL qsort_desc(array,idx,bot+1,hi)
5842  !
5843  RETURN
5844  !/
5845 199 FORMAT (/' *** WAVEWATCH III ERROR IN W3SYSTRK : '/ &
5846  ' QSORT ARRAY IS EMPTY' )
5847 201 FORMAT (/' *** WAVEWATCH III ERROR IN W3SYSTRK : '/ &
5848  ' QSORT ARRAY SIZE AND INDEX ARRAY SIZE MISMATCH' )
5849 203 FORMAT (/' *** WAVEWATCH III ERROR IN W3SYSTRK : '/ &
5850  ' QSORT ARRAY INDEX OUT OF LOWER BOUND' )
5851 205 FORMAT (/' *** WAVEWATCH III ERROR IN W3SYSTRK : '/ &
5852  ' QSORT ARRAY INDEX OUT OF UPPER BOUND' )
5853  !/

Referenced by sort().

◆ setdiff()

subroutine w3strkmd::setdiff ( real, dimension(insize1), intent(in)  INARRAY1,
integer, intent(in)  INSIZE1,
real, dimension(insize2), intent(in)  INARRAY2,
integer, intent(in)  INSIZE2,
real, dimension(:), pointer  OUTARRAY,
integer, intent(out)  OUTSIZE 
)

Definition at line 4937 of file w3strkmd.F90.

4937  !/
4938  !/ +-----------------------------------+
4939  !/ | WAVEWATCH III NOAA/NCEP |
4940  !/ | A. J. van der Westhuysen |
4941  !/ | Jeff Hanson |
4942  !/ | Eve-Marie Devaliere |
4943  !/ | FORTRAN 95 |
4944  !/ | Last update : 20-Dec-2016 |
4945  !/ +-----------------------------------+
4946  !/
4947  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
4948  !/ by Jeff Hanson & Eve-Marie Devaliere
4949  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
4950  !/ 20-Dec-2016 : Add quicksort algorithm (S.Zieger) ( version 5.16 )
4951  !/
4952  !/ Copyright 2009-2013 National Weather Service (NWS),
4953  !/ National Oceanic and Atmospheric Administration. All rights
4954  !/ reserved. WAVEWATCH III is a trademark of the NWS.
4955  !/ No unauthorized use without permission.
4956  !/
4957  IMPLICIT NONE
4958  !
4959  ! 1. Purpose :
4960  !
4961  ! (i) Returns the elements in INARRAY1 that are not in INARRAY2.
4962  ! (ii) Sort the resulting array in ascending order.
4963  !
4964  ! 2. Method
4965  !
4966  ! 3. Parameters :
4967  !
4968  ! Parameter list
4969  ! ----------------------------------------------------------------
4970  ! INARRAY1 REAL ARR input Input array
4971  ! INSIZE1 INTEGER input Size of input array
4972  ! INARRAY2 REAL ARR input Input array
4973  ! INSIZE2 INTEGER input Size of input array
4974  ! OUTARRAY REAL ARR output Output array
4975  ! OUTSIZE INTEGER output Size of output array (number of unique elements)
4976 
4977  INTEGER :: INSIZE1, INSIZE2, OUTSIZE
4978  REAL :: INARRAY1(INSIZE1), INARRAY2(INSIZE2)
4979  REAL, POINTER :: OUTARRAY(:)
4980 
4981  INTENT (IN) inarray1, insize1, inarray2, insize2
4982  INTENT (OUT) outsize
4983  !
4984  ! Local variables
4985  ! ----------------------------------------------------------------
4986  INTEGER :: I,J,K
4987  REAL :: TEMP(INSIZE1)
4988  REAL :: ARRAY1(INSIZE1),ARRAY2(INSIZE2)
4989  REAL :: ID1(INSIZE1),ID2(INSIZE2)
4990  LOGICAL :: LOOP
4991  !
4992  ! 4. Subroutines used :
4993  !
4994  ! Name Type Scope Description
4995  ! ----------------------------------------------------------------
4996  ! QSORT Subr. Private Quicksort algorithm
4997  !
4998  ! 5. Subroutines calling
4999  !
5000  ! printFinalSys
5001  ! combineSys
5002  ! timeTrackingV2
5003  !
5004  ! 6. Error messages :
5005  !
5006  ! 7. Remarks :
5007  !
5008  ! 8. Structure :
5009  !
5010  ! -
5011  !
5012  ! 9. Switches :
5013  !
5014  ! None defined yet.
5015  !
5016  ! 10. Source code :
5017  !
5018  !/ ------------------------------------------------------------------- /
5019  IF ( (insize1).EQ.0 ) THEN
5020  outsize = 0
5021  ALLOCATE(outarray(outsize))
5022  ELSE IF ( insize2.EQ.0 ) THEN
5023  CALL unique(inarray1,insize1,outarray,outsize)
5024  ELSE
5025  !/ --- Setup input arrays. ---
5026  DO i=1,insize1
5027  array1(i) = inarray1(i)
5028  id1(i) = real(i)
5029  END DO
5030  DO i=1,insize2
5031  array2(i) = inarray2(i)
5032  id2(i) = real(i)
5033  END DO
5034  !/
5035  !/ --- Sort input arrays. ---
5036  CALL qsort(array1,id1,1,insize1)
5037  CALL qsort(array2,id2,1,insize2)
5038  !/
5039  !/ --- Initialise indices. ---
5040  i = 1
5041  j = 1
5042  k = 1
5043  !/
5044  !/ --- Allocate and initialize temporary output ---
5045  temp(:) = 9999.
5046  !/
5047  !/ --- Loop though both arrays by incrementing I,J. ---
5048  loop = .true.
5049  DO WHILE ( loop )
5050  !/
5051  IF ( array1(i).LT.array2(j) .OR. &
5052  array1(i).GT.array2(insize2) ) THEN
5053  !/ --- Populate output array. Check for dumplicates
5054  !/ in output array. ---
5055  IF ( k.EQ.1 ) THEN
5056  temp(k) = array1(i)
5057  k = k + 1
5058  ELSE IF ( temp(k-1).LT.array1(i) ) THEN
5059  temp(k) = array1(i)
5060  k = k + 1
5061  END IF
5062  i = i + 1
5063  ELSE IF ( array2(j).LT.array1(i) ) THEN
5064  j = j + 1
5065  ELSE
5066  i = i + 1
5067  j = j + 1
5068  END IF
5069  !/ --- Check for exit the loop. ---
5070  IF ( i.GT.insize1 ) THEN
5071  loop = .false.
5072  END IF
5073  !/ --- Make sure array pointer I,J are within array bounds. ---
5074  i = min(i,insize1)
5075  j = min(j,insize2)
5076  !/
5077  END DO
5078  !/
5079  !/ --- Allocate output array ---
5080  outsize = k-1
5081  ALLOCATE(outarray(outsize))
5082  !/ --- Transfer output from temporary array to output array. ---
5083  DO i=1,outsize
5084  outarray(i) = temp(i)
5085  END DO
5086  END IF
5087  !/
5088  RETURN
5089  !/

References qsort(), and unique().

Referenced by combinesys(), and printfinalsys().

◆ sort()

subroutine w3strkmd::sort ( real, dimension(insize), intent(in)  INARRAY,
integer, intent(in)  INSIZE,
real, dimension(insize), intent(out)  OUTARRAY,
integer, dimension(insize), intent(out)  IY,
character, intent(in)  DIRECTION 
)

Definition at line 4817 of file w3strkmd.F90.

4817  !/
4818  !/ +-----------------------------------+
4819  !/ | WAVEWATCH III NOAA/NCEP |
4820  !/ | A. J. van der Westhuysen |
4821  !/ | Jeff Hanson |
4822  !/ | Eve-Marie Devaliere |
4823  !/ | FORTRAN 95 |
4824  !/ | Last update : 20-Dec-2016 |
4825  !/ +-----------------------------------+
4826  !/
4827  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
4828  !/ by Jeff Hanson & Eve-Marie Devaliere
4829  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
4830  !/ 20-Dec-2016 : Add quicksort algorithm (S. Zieger) ( version 5.16 )
4831  !/
4832  !/ Copyright 2009-2013 National Weather Service (NWS),
4833  !/ National Oceanic and Atmospheric Administration. All rights
4834  !/ reserved. WAVEWATCH III is a trademark of the NWS.
4835  !/
4836  IMPLICIT NONE
4837  !
4838  ! 1. Purpose :
4839  !
4840  ! Sorts the array INARRAY in ascending (Direction = 'A') or
4841  ! descending (Direciton = 'D') order. The sorted array is
4842  ! stored in OUTARRAY, and the sorted array of the original
4843  ! indices is stored in IY.
4844  !
4845  ! 2. Method
4846  !
4847  ! Sort algorithm based on quicksort.
4848  !
4849  ! 3. Parameters :
4850  !
4851  ! Parameter list
4852  ! ----------------------------------------------------------------
4853  ! INARRAY REAL ARR input Input array
4854  ! INSIZE INTEGER input Size of input array
4855  ! OUTARRAY REAL ARR output Sorted output array
4856  ! IY INTEGER ARR output Sorted array of the original indices
4857 
4858  CHARACTER :: DIRECTION *1
4859  INTEGER :: INSIZE
4860  INTEGER :: IY(INSIZE)
4861  REAL :: INARRAY(INSIZE), OUTARRAY(INSIZE)
4862 
4863  INTENT (IN) inarray, insize, direction
4864  INTENT (OUT) outarray, iy
4865  !
4866  ! Local variables
4867  ! ----------------------------------------------------------------
4868  ! INARRAY - array of values to be sorted
4869  ! IY - array to be carried with X (all swaps of X elements are ??? EDIT!
4870  ! matched in IY . After the sort IY(J) contains the original
4871  ! postition of the value X(J) in the unsorted X array.
4872  ! N - number of values in array X to be sorted
4873 
4874  INTEGER :: I
4875  REAL :: IND(INSIZE)
4876  !
4877  ! 4. Subroutines used :
4878  !
4879  ! Name Type Module Description
4880  ! ----------------------------------------------------------------
4881  ! -
4882  !
4883  ! 5. Subroutines calling
4884  !
4885  ! printFinalSys
4886  ! combineSys
4887  ! timeTrackingV2
4888  !
4889  ! 6. Error messages :
4890  !
4891  ! 7. Remarks :
4892  !
4893  ! 8. Structure :
4894  !
4895  ! -
4896  !
4897  ! 9. Switches :
4898  !
4899  ! None defined yet.
4900  !
4901  ! 10. Source code :
4902  !
4903  !/ ------------------------------------------------------------------- /
4904 
4905  ! Sort OUTARRAY in as/decending order
4906 
4907  IF (insize.EQ.0) THEN
4908  WRITE(20,*) '*** In Subr. SORT: Input array has length=0 !!!'
4909  ELSE
4910 
4911  DO i = 1, insize
4912  outarray(i) = inarray(i)
4913  ind(i) = real(i)
4914  END DO
4915 
4916  IF (direction .EQ. 'A') THEN
4917  CALL qsort(outarray,ind,1,insize)
4918  ELSE IF (direction .EQ. 'D') THEN
4919  CALL qsort_desc(outarray,ind,1,insize)
4920  END IF
4921 
4922  END IF
4923  !
4924  !/ --- Cast index array to integer. ---
4925  DO i = 1, insize
4926  iy(i) = int(ind(i))
4927  END DO
4928  !
4929  RETURN
4930  !

References qsort(), and qsort_desc().

Referenced by combinesys(), printfinalsys(), and timetrackingv2().

◆ spiraltrackv3()

subroutine w3strkmd::spiraltrackv3 ( type(dat2d), intent(inout)  wsdat,
real, intent(in)  dirKnob,
real, intent(in)  perKnob,
real, intent(in)  wetPts,
real, intent(in)  hsKnob,
real, intent(in)  seedLat,
real, intent(in)  seedLon,
integer  maxSys,
type(system), dimension(:), pointer  sys 
)

Definition at line 1749 of file w3strkmd.F90.

1749  !/
1750  !/ +-----------------------------------+
1751  !/ | WAVEWATCH III NOAA/NCEP |
1752  !/ | A. J. van der Westhuysen |
1753  !/ | Jeff Hanson |
1754  !/ | Eve-Marie Devaliere |
1755  !/ | FORTRAN 95 |
1756  !/ | Last update : 4-Jan-2013 |
1757  !/ +-----------------------------------+
1758  !/
1759  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
1760  !/ by Jeff Hanson & Eve-Marie Devaliere
1761  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
1762  !/
1763  !/ Copyright 2009-2013 National Weather Service (NWS),
1764  !/ National Oceanic and Atmospheric Administration. All rights
1765  !/ reserved. WAVEWATCH III is a trademark of the NWS.
1766  !/ No unauthorized use without permission.
1767  !/
1768  IMPLICIT NONE
1769  !
1770  ! 1. Purpose :
1771  !
1772  ! Performs the spatial spiral tracking for a given time step
1773  !
1774  ! 2. Method
1775  !
1776  ! Index convention on grid:
1777  !
1778  ! j
1779  ! ^
1780  ! |+(1,maxJ) +(maxI,maxJ)
1781  ! |
1782  ! |
1783  ! |
1784  ! |
1785  ! |
1786  ! |
1787  ! |(1,1) +(maxI,1)
1788  ! +----------------------> i
1789  !
1790  ! 3. Parameters :
1791  !
1792  ! Parameter list
1793  ! ----------------------------------------------------------------
1794  ! dirKnob Real input Parameter in direction for combining fields in space
1795  ! perKnob Real input Parameter in period for combining fields in space
1796  ! wetPts Real input Percentage of wet points for purging fields (fraction)
1797  ! hsKnob Real input Parameter in wave height for purging fields
1798  ! seedLat Real input Start Lat for tracking spiral (if =0 centre of field is used)
1799  ! seedLon Real input Start Lon for tracking spiral (if =0 centre of field is used)
1800  ! wsdat Real arr output Input 2d (gridded) data structure to be spiral tracked
1801  ! maxSys Int output Maximum number of partition systems
1802  ! sys Type(system) output Final set of tracked systems, for one time level
1803  !
1804  TYPE(dat2d) :: wsdat
1805  REAL :: dirKnob,perKnob,wetPts,hsKnob,seedLat,seedLon
1806  INTEGER :: maxSys
1807  TYPE(system), POINTER :: sys(:)
1808 
1809  INTENT (IN) wetpts,dirknob,perknob,hsknob,seedlat,seedlon
1810  INTENT (IN OUT) wsdat
1811  ! INTENT (OUT) maxSys,sys
1812  !
1813  ! Local variables
1814  ! ----------------------------------------------------------------
1815  ! ngbrExt Int How far do we want the neighbour to be considered
1816  ! combine Int Toggle (1=combine wave systems; 0=do not combine)
1817  ! maxI,MaxJ Int Dimensions of the 2d (gridded) data wsdat
1818  ! deltaLat Real Delta in kilometers between 2 pts (in latitude)
1819  !
1820  LOGICAL :: first
1821  CHARACTER :: way *1
1822  INTEGER :: ngbrExt, combine, maxI, maxJ, i, j, oldJ
1823  INTEGER :: horizStepCount, vertStepCount, checkCount, sc, &
1824  maxPts, landPts, horizBorder, vertBorder, m, k, &
1825  stepCount
1826  REAL :: deltaLat, minLat, maxLat, minLon, maxLon
1827  !
1828  ! 4. Subroutines used :
1829  !
1830  ! Name Type Module Description
1831  ! ----------------------------------------------------------------
1832  ! findWay
1833  ! findNext
1834  ! findSys
1835  ! combineWaveSystems
1836  !
1837  ! 5. Subroutines calling
1838  !
1839  ! waveTracking_NWS_V2
1840  !
1841  ! 6. Error messages :
1842  !
1843  ! 7. Remarks :
1844  !
1845  ! 8. Structure :
1846  !
1847  ! -
1848  !
1849  ! 9. Switches :
1850  !
1851  ! None defined yet.
1852  !
1853  ! 10. Source code :
1854  !
1855  !/ ------------------------------------------------------------------- /
1856 
1857  ! Routine starts by identifying the starting point. Choose the 'center' of the domain
1858  ! Set the search distance for neighbors:
1859  ! 1: 1 row and column out, i.e. the 8 neighbors around the current point
1860  ! 2: 2 rows and columns out... etc.
1861  ngbrext=1
1862  combine=1
1863  WRITE(20,*) 'In spiralTrackV3: combine = ',combine
1864 
1865  maxi = wsdat%maxi
1866  maxj = wsdat%maxj
1867  IF ( (seedlat.EQ.0).OR.(seedlon.EQ.0) ) THEN
1868  i=nint(real(maxi)/2.)
1869  j=nint(real(maxj)/2.)
1870  WRITE(20,*) 'In spiralTrackV3, i=NINT(maxI/2.) =',i
1871  WRITE(20,*) 'In spiralTrackV3, j=NINT(maxJ/2.) =',j
1872  ELSE
1873  i=1
1874  j=1
1875  DO WHILE ( (wsdat%lat(1,j).LT.seedlat).AND.(j.LT.wsdat%maxj) ) !40.PAR !Improve with SWAN's indice identification
1876  j=j+1
1877  END DO
1878  DO WHILE ( (wsdat%lon(i,1).LT.seedlon).AND.(i.LT.wsdat%maxi) )
1879  i=i+1
1880  END DO
1881  END IF
1882  ! In case center point is land point...
1883  IF (wsdat%par(i,j)%checked.EQ.-1) THEN
1884  oldj=j
1885  DO WHILE (wsdat%par(i,j)%checked.EQ.-1)
1886  j=j+1
1887  IF (j.EQ.maxj) THEN
1888  j=oldj
1889  i=i+1
1890  oldj=oldj+1
1891  END IF
1892  END DO
1893  END IF
1894  ! Compute distance in km between 2 grid points (at equator)
1895  deltalat=(wsdat%lat(i,j)-wsdat%lat(i,j-1))*111.18
1896 
1897  ! Starts the spiral
1898  ! Intitiate variables
1899  horizstepcount=0
1900  vertstepcount=0
1901  way='R'
1902  first=.true.
1903  checkcount=1
1904  maxsys=0
1905  landpts=0
1906 
1907  minlat=minval(wsdat%lat)
1908  maxlat=maxval(wsdat%lat)
1909  minlon=minval(wsdat%lon)
1910  maxlon=maxval(wsdat%lon)
1911 
1912  horizborder=0
1913  vertborder=0
1914  DO WHILE (checkcount.LE.(maxi*maxj-3) )
1915  ! From the direction (way) we were going before, find which direction we
1916  ! are going now and how many 'step' we need to take
1917  CALL findway(way, horizstepcount, vertstepcount, &
1918  vertborder, horizborder, stepcount)
1919  IF (first) THEN
1920  m=0
1921  DO k=1,length(wsdat%par(i,j)%hs, &
1922  SIZE(wsdat%par(i,j)%hs),9999.)
1923  IF ( (wsdat%par(i,j)%hs(k).EQ.0.).AND. &
1924  (wsdat%par(i,j)%tp(k).EQ.0.) ) THEN
1925  wsdat%par(i,j)%sys(k)=-1
1926  ELSE
1927  m=m+1
1928  wsdat%par(i,j)%sys(k)=m
1929  END IF
1930  END DO
1931 
1932  wsdat%par(i,j)%checked=1
1933  checkcount=checkcount+1
1934  first=.false.
1935  END IF
1936  DO sc = 1, stepcount
1937  CALL findnext (i,j,maxi,maxj,way,vertborder,horizborder)
1938  IF ( wsdat%par(i,j)%checked.EQ.-1 ) THEN
1939  ! Land point is one of our grid points, so we need to update counter
1940  checkcount=checkcount+1
1941  landpts=landpts+1
1942  ! So that we don't count the land points twice....
1943  wsdat%par(i,j)%checked=-2
1944  ELSE IF ( wsdat%par(i,j)%checked.EQ.0 ) THEN
1945  ! Hasn't been checked yet and is not land point
1946  checkcount=checkcount+1
1947  CALL findsys(i, j, wsdat, maxsys, ngbrext, maxi, maxj, &
1948  perknob, dirknob, hsknob)
1949  END IF
1950  END DO
1951  END DO
1952  ! wetPts% of wet points
1953  maxpts=nint(wetpts*(maxi*maxj-1))
1954  !
1955  WRITE(20,*) 'Call combineWaveSystems...'
1956  CALL combinewavesystems(wsdat,maxsys,maxpts,maxi,maxj, &
1957  perknob,dirknob,hsknob,combine,sys)
1958 
1959  RETURN

References combinewavesystems(), findnext(), findsys(), findway(), and length().

Referenced by wavetracking_nws_v2().

◆ std()

real function w3strkmd::std ( real, dimension(n)  ARRAY,
integer  N 
)

Definition at line 5554 of file w3strkmd.F90.

5554  !/
5555  !/ +-----------------------------------+
5556  !/ | WAVEWATCH III NOAA/NCEP |
5557  !/ | A. J. van der Westhuysen |
5558  !/ | Jeff Hanson |
5559  !/ | Eve-Marie Devaliere |
5560  !/ | FORTRAN 95 |
5561  !/ | Last update : 4-Jan-2013 |
5562  !/ +-----------------------------------+
5563  !/
5564  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
5565  !/ by Jeff Hanson & Eve-Marie Devaliere
5566  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
5567  !/
5568  !/ Copyright 2009-2013 National Weather Service (NWS),
5569  !/ National Oceanic and Atmospheric Administration. All rights
5570  !/ reserved. WAVEWATCH III is a trademark of the NWS.
5571  !/ No unauthorized use without permission.
5572  !/
5573  IMPLICIT NONE
5574  !
5575  ! 1. Purpose :
5576  !
5577  ! Computes standard deviation.
5578  !
5579  ! 3. Parameters :
5580  !
5581  ! Parameter list
5582  ! ----------------------------------------------------------------
5583  ! ARRAY REAL Input array for which to compute the std dev.
5584  ! N INT Size of ARRAY
5585  !
5586  REAL :: ARRAY(N)
5587  INTEGER :: N
5588  !
5589  ! Local variables
5590  ! ----------------------------------------------------------------
5591  REAL :: MN
5592  !
5593  ! 10. Source code :
5594  !
5595  !/ ------------------------------------------------------------------- /
5596  IF (n.GT.1) THEN
5597  mn = sum(array)/n
5598  std = sqrt( 1/(real(n)-1)*sum( (array(:)-mn)**2 ) )
5599  ELSE
5600  std = 0.
5601  END IF
5602 
5603  RETURN

Referenced by combinewavesystems().

◆ swapi4()

integer(kind=4) function w3strkmd::swapi4 ( integer(kind=4), intent(in)  INT4)

Definition at line 5858 of file w3strkmd.F90.

5858  !/
5859  !/ +-----------------------------------+
5860  !/ | WAVEWATCH III NOAA/NCEP |
5861  !/ | S. Zieger |
5862  !/ | FORTRAN 90 |
5863  !/ | Last update : 03-Jan-2017 |
5864  !/ +-----------------------------------+
5865  !/
5866  !/ 03-Jan-2017 : Origination ( version 5.16 )
5867  !/ (S. Zieger)
5868  !/
5869  ! 1. Purpose :
5870  !
5871  ! Return a Byte-swapped integer (size of 4 bytes)
5872  !
5873  ! 2. Source code :
5874  !
5875  !/ ------------------------------------------------------------------- /
5876  IMPLICIT NONE
5877  INTEGER(KIND=4), INTENT(IN) :: INT4
5878  INTEGER(KIND=4) :: INT4SWP
5879  !/
5880  ! Local variables
5881  ! ----------------------------------------------------------------
5882  INTEGER(KIND=1), DIMENSION(4) :: BYTEIN, BYTEOUT
5883  !/
5884  bytein = transfer(int4, bytein)
5885  byteout = (/bytein(4),bytein(3),bytein(2),bytein(1)/)
5886  int4swp = transfer(byteout, int4swp)
5887  !/
5888  RETURN
5889  !/

Referenced by wavetracking_nws_v2().

◆ timetrackingv2()

subroutine w3strkmd::timetrackingv2 ( type(timsys), dimension(:), pointer  sysA,
integer, dimension(:), pointer  maxSys,
real, intent(in)  tpTimeKnob,
real, intent(in)  dirTimeKnob,
integer, intent(in)  ts0,
integer, intent(out)  maxGroup,
real  dt,
real  lonext,
real  latext,
integer, intent(in)  maxI,
integer, intent(in)  maxJ 
)

Definition at line 1968 of file w3strkmd.F90.

1968  !/
1969  !/ +-----------------------------------+
1970  !/ | WAVEWATCH III NOAA/NCEP |
1971  !/ | A. J. van der Westhuysen |
1972  !/ | Jeff Hanson |
1973  !/ | Eve-Marie Devaliere |
1974  !/ | FORTRAN 95 |
1975  !/ | Last update : 4-Jan-2013 |
1976  !/ +-----------------------------------+
1977  !/
1978  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
1979  !/ by Jeff Hanson & Eve-Marie Devaliere
1980  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
1981  !/
1982  !/ Copyright 2009-2013 National Weather Service (NWS),
1983  !/ National Oceanic and Atmospheric Administration. All rights
1984  !/ reserved. WAVEWATCH III is a trademark of the NWS.
1985  !/ No unauthorized use without permission.
1986  !/
1987  IMPLICIT NONE
1988  !
1989  ! 1. Purpose :
1990  !
1991  ! Performs the time tracking of the systems identified within
1992  ! the subroutine spiralTrackV3.
1993  !
1994  ! 2. Method
1995  !
1996  ! -
1997  !
1998  ! 3. Parameters :
1999  !
2000  ! Parameter list
2001  ! ----------------------------------------------------------------
2002  ! Note: perKnob, dirKnob in Matlab version replaced by tpTimeKnob, dirTimeKnob!
2003  !
2004  ! sysA TYPE(timsys) in/out Final set of spatially and temporally tracked systems
2005  ! dirTimeKnob Real input Parameter in direction for combining fields in time
2006  ! tpTimeKnob Real input Parameter in period for combining fields in time
2007  ! ts0 Int input Time step to which default grp values are associated
2008  ! maxSys Int arr input Total number of systems per time level
2009  ! maxGroup Int output Maximum number of wave systems ("groups") tracked in time
2010  ! lonext Real input Longitudinal extent of domain
2011  ! latext Real input Latitudinal extent of domain
2012  ! maxI, maxJ Int input Maximum indices of wave field
2013  !
2014  TYPE(timsys), POINTER :: sysA(:)
2015  INTEGER, POINTER :: maxSys(:)
2016  REAL :: dirTimeKnob, tpTimeKnob
2017  INTEGER :: ts0, maxGroup
2018  REAL :: dt
2019  REAL :: lonext, latext
2020  INTEGER :: maxI, maxJ
2021 
2022  INTENT (IN) tptimeknob, dirtimeknob, ts0, maxi, maxj
2023  ! INTENT (IN OUT) sysA
2024  INTENT (OUT) maxgroup
2025  !
2026  ! Local variables
2027  ! ----------------------------------------------------------------
2028  ! ic Int Counter for wave systems
2029  ! ts1 Int Adjusted initial time step in case ts0 has only empty systems
2030  !
2031  LOGICAL :: file_exists
2032  CHARACTER :: dummy*23
2033  TYPE(sysmemory) :: sysMem(50) !!! 50 memory spaces should be enough Check!!!
2034  INTEGER :: leng, l, i, ii, j, k, kk, idir, numSys, &
2035  counter, new, DIFSIZE, tpMinInd, dirMinInd, used, ok
2036  REAL :: Tb, deltaPer, deltaDir, tpMinVal, dirMinVal, &
2037  dirForTpMin, tpForDirMin
2038  REAL, ALLOCATABLE :: sysOrdered(:), TEMP(:), dirs(:)
2039  REAL, POINTER :: DIFARR(:)
2040  INTEGER, ALLOCATABLE :: indSorted(:), alreadyUsed(:), allInd(:)
2041  INTEGER, ALLOCATABLE :: ind(:), ind2(:)
2042  INTEGER :: ts1
2043  REAL, ALLOCATABLE :: GOF(:,:), GOFMinVal(:), GOFMinInd(:), &
2044  Tbsysmem(:), deltaDirsysmem(:), &
2045  deltaPersysmem(:),m1sysmem(:),m2sysmem(:)
2046  REAL :: m1, m2
2047  REAL :: lonmean, latmean, dmndiag
2048  INTEGER :: npnts, npnts2
2049  REAL, ALLOCATABLE :: mnlonlist(:), mnlatlist(:), mndist(:)
2050  REAL, POINTER :: dummy1(:),dummy2(:),dummy3(:)
2051  INTEGER, ALLOCATABLE :: olsize(:)
2052  REAL :: TEMP1, TEMP2
2053  INTEGER :: iii, jj, ll, idup
2054  !
2055  ! 4. Subroutines used :
2056  !
2057  ! Name Type Module Description
2058  ! ----------------------------------------------------------------
2059  ! SORT
2060  ! SETDIFF
2061  !
2062  ! 5. Subroutines calling
2063  !
2064  ! waveTracking_NWS_V2
2065  !
2066  !
2067  ! 6. Error messages :
2068  !
2069  ! 7. Remarks :
2070  !
2071  ! 8. Structure :
2072  !
2073  ! -
2074  !
2075  ! 9. Switches :
2076  !
2077  ! None defined yet.
2078  !
2079  ! 10. Source code :
2080  !
2081  !/ ------------------------------------------------------------------- /
2082 
2083  ! Associate default grp value to time step 1
2084  WRITE(20,*) 'TIME TRACKING'
2085  WRITE(20,*) 'Inside timeTrackingV2: SIZE(sysA(1)%sys) =', &
2086  SIZE(sysa(1)%sys)
2087  WRITE(20,*) 'Inside timeTrackingV2: maxSys(1) =',maxsys(1)
2088  WRITE(20,*) 'ts0 = ',ts0
2089 
2090  ts1 = ts0
2091 
2092  ! Skip initial time steps with empty systems (e.g. when starting from rest)
2093  DO i = ts1, SIZE(sysa)
2094  IF (SIZE(sysa(ts1)%sys).EQ.0) ts1 = ts1+1
2095  ! No non-empty systems found
2096  IF (ts1.GT.SIZE(sysa)) THEN
2097  maxgroup = 0
2098  GOTO 2000
2099  END IF
2100  END DO
2101  WRITE(20,*) 'TS = ',ts1
2102 
2103  IF (SIZE(sysa(ts1)%sys).GT.0) THEN
2104  ! Initialize system memory groups
2105  sysa(ts1)%sys(:)%grp = 9999
2106  sysmem(:)%grp = 9999
2107  sysmem(:)%nPoints = 0
2108  sysmem(:)%lonMean = 9999.
2109  sysmem(:)%latMean = 9999.
2110  sysmem(:)%tpMean = 9999.
2111  sysmem(:)%dirMean = 9999.
2112  sysmem(:)%updated = -9999
2113  sysmem(:)%length = 0
2114  DO iii = 1,50
2115  ALLOCATE(sysmem(iii)%indx(maxi*maxj))
2116  sysmem(iii)%indx = 9999
2117  END DO
2118 
2119  INQUIRE(file="sys_restart.ww3", exist=file_exists)
2120  IF (file_exists) THEN
2121  ! Use groups from wave tracking hotfile
2122  WRITE(20,*) '*** Using group memory hotfile'
2123  OPEN(unit=12,file='sys_restart.ww3',status='old')
2124  READ(12,'(A23,I10)') dummy,maxgroup
2125  WRITE(20,*) 'Reading ',maxgroup,' systems'
2126  DO k = 1,maxgroup
2127  READ(12,'(A23,I10)') dummy,sysmem(k)%grp
2128  READ(12,'(A23,I10)') dummy,sysmem(k)%nPoints
2129  READ(12,'(A23,F10.4)') dummy,sysmem(k)%lonMean
2130  READ(12,'(A23,F10.4)') dummy,sysmem(k)%latMean
2131  READ(12,'(A23,F10.3)') dummy,sysmem(k)%tpMean
2132  READ(12,'(A23,F10.3)') dummy,sysmem(k)%dirMean
2133  READ(12,'(A23,I10)') dummy,sysmem(k)%updated
2134  READ(12,'(A23,I10)') dummy,sysmem(k)%length
2135  DO j = maxj,1,-1
2136  READ(12,*) (sysmem(k)%indx((j-1)*maxi+i), i = 1,maxi)
2137  END DO
2138  !Reset update counter
2139  sysmem(k)%updated = 0
2140  END DO
2141  CLOSE(12)
2142  ts1 = ts1-1
2143  ELSE
2144  ! Set up the group number array for the first time level to be tracked
2145  ALLOCATE( sysordered(maxsys(ts1)) )
2146  ALLOCATE( indsorted(maxsys(ts1)) )
2147  CALL sort (real(sysa(ts1)%sys(1:maxsys(ts1))%nPoints), &
2148  maxsys(ts1),sysordered,indsorted,'D')
2149  sysa(ts1)%sys(1:maxsys(ts1)) = sysa(ts1)%sys(indsorted)
2150  IF (ALLOCATED(sysordered)) DEALLOCATE(sysordered)
2151  IF (ALLOCATED(indsorted)) DEALLOCATE(indsorted)
2152 
2153  ! Set the initial long-term system memory
2154  DO i = 1, maxsys(ts1)
2155  sysa(ts1)%sys(i)%grp = i
2156  ! Set initial values of long-term system memory
2157  sysmem(i)%grp = i
2158  sysmem(i)%nPoints = sysa(ts1)%sys(i)%nPoints
2159  sysmem(i)%lonMean = &
2160  sum(sysa(ts1)%sys(i)%lon(1:sysmem(i)%nPoints))/&
2161  sysmem(i)%nPoints
2162  sysmem(i)%latMean = &
2163  sum(sysa(ts1)%sys(i)%lat(1:sysmem(i)%nPoints))/&
2164  sysmem(i)%nPoints
2165  !070512----------- Weight averages with Hm0 ---------------------
2166  temp1 = 0.
2167  temp2 = 0.
2168  DO iii = 1,sysmem(i)%nPoints
2169  temp1 = temp1 + &
2170  (sysa(ts1)%sys(i)%hs(iii)**2)*sysa(ts1)%sys(i)%lon(iii)
2171  temp2 = temp2 + &
2172  (sysa(ts1)%sys(i)%hs(iii)**2)*sysa(ts1)%sys(i)%lat(iii)
2173  END DO
2174  sysmem(i)%lonMean = temp1/&
2175  max(sum(sysa(ts1)%sys(i)%hs(1:sysmem(i)%nPoints)**2),&
2176  0.001)
2177  sysmem(i)%latMean = temp2/&
2178  max(sum(sysa(ts1)%sys(i)%hs(1:sysmem(i)%nPoints)**2),&
2179  0.001)
2180  !070512----------- Weight averages with Hm0 ---------------------
2181  sysmem(i)%tpMean = sysa(ts1)%sys(i)%tpMean
2182  sysmem(i)%dirMean = sysa(ts1)%sys(i)%dirMean
2183  sysmem(i)%updated = ts1
2184  sysmem(i)%length = 1
2185  !071012----------- Grid point indexing --------------------------
2186  DO iii = 1,sysmem(i)%nPoints
2187  sysmem(i)%indx(iii) = (sysa(ts1)%sys(i)%j(iii)-1)*maxi +&
2188  sysa(ts1)%sys(i)%i(iii)
2189  END DO
2190  !071012----------- Grid point indexing --------------------------
2191  END DO
2192  maxgroup = maxsys(ts1)
2193  ! i = ts1
2194  END IF
2195 
2196  !******** Test output ***********************
2197  DO i = 1, maxgroup
2198  WRITE(20,*) 'sysMem(',i,')%grp =',sysmem(i)%grp
2199  WRITE(20,*) 'sysMem(',i,')%nPoints =',sysmem(i)%nPoints
2200  WRITE(20,*) 'sysMem(',i,')%lonMean =',sysmem(i)%lonMean
2201  WRITE(20,*) 'sysMem(',i,')%latMean =',sysmem(i)%latMean
2202  WRITE(20,*) 'sysMem(',i,')%tpMean =',sysmem(i)%tpMean
2203  WRITE(20,*) 'sysMem(',i,')%dirMean =',sysmem(i)%dirMean
2204  WRITE(20,*) 'sysMem(',i,')%updated =',sysmem(i)%updated
2205  WRITE(20,*) 'sysMem(',i,')%length =',sysmem(i)%length
2206  END DO
2207  !********************************************
2208  END IF
2209 
2210  ! Loop over all time levels to track systems in time
2211  WRITE(20,*) 'Number of time levels = ',SIZE(sysa)
2212  DO i = (ts1+1), SIZE(sysa)
2213  WRITE(20,*) 'TS = ',i
2214 
2215  IF (SIZE(sysa(i)%sys).GT.0) THEN
2216  ! *** Added: 02/29/12 *************************************
2217  ! Sort groups, so that larger systems get associated first
2218  ALLOCATE( sysordered(maxsys(i)) )
2219  ALLOCATE( indsorted(maxsys(i)) )
2220  CALL sort (real(sysa(i)%sys(1:maxsys(i))%nPoints), &
2221  maxsys(i),sysordered,indsorted,'D')
2222  sysa(i)%sys(1:maxsys(i)) = sysa(i)%sys(indsorted)
2223  IF (ALLOCATED(sysordered)) DEALLOCATE(sysordered)
2224  IF (ALLOCATED(indsorted)) DEALLOCATE(indsorted)
2225  ! *** Added: 02/29/12 *************************************
2226 
2227  ! Initialize groups ! Optimize?
2228  sysa(i)%sys(:)%grp = 9999 ! Optimize?
2229  counter = 0
2230  leng = length(real(sysmem(:)%grp), &
2231  SIZE(sysmem(:)%grp),real(9999))
2232  ALLOCATE( alreadyused(leng+10) ) !Make space for 10 new potential entries. Improve!!!
2233  WRITE(20,*) 'sysMem(1:leng)%grp =', &
2234  sysmem(1:leng)%grp
2235  ALLOCATE( allind(leng) )
2236  alreadyused(:) = 0
2237  allind(:) = sysmem(1:leng)%grp
2238 
2239  !071212-----GoF 2D-------------------------------
2240  ALLOCATE( ind(SIZE(allind)) )
2241  ind(:) = allind
2242  ALLOCATE( ind2(SIZE(ind)) )
2243  DO ii = 1, SIZE(ind)
2244  ind2(ii) = findfirst(real(allind),SIZE(allind), &
2245  REAL(ind(ii)))
2246  END DO
2247  ! Define 2D array for evaluating best fit for systems
2248  ALLOCATE( gof(maxsys(i),maxgroup) )
2249  ALLOCATE( gofminval(maxgroup) )
2250  ALLOCATE( gofminind(maxgroup) )
2251  ALLOCATE( tbsysmem(maxgroup) )
2252  ALLOCATE( deltadirsysmem(maxgroup) )
2253  ALLOCATE( deltapersysmem(maxgroup) )
2254  ALLOCATE( m1sysmem(maxgroup) )
2255  ALLOCATE( m2sysmem(maxgroup) )
2256  !071212-----GoF 2D-------------------------------
2257  DO j = 1, maxsys(i)
2258  npnts = sysa(i)%sys(j)%nPoints
2259  lonmean = sum(sysa(i)%sys(j)%lon(1:npnts))/npnts
2260  latmean = sum(sysa(i)%sys(j)%lat(1:npnts))/npnts
2261  !070512----------- Weight averages with Hm0 ---------------------
2262  temp1 = 0.
2263  temp2 = 0.
2264  DO iii = 1,npnts
2265  temp1 = temp1 + &
2266  (sysa(i)%sys(j)%hs(iii)**2)*sysa(i)%sys(j)%lon(iii)
2267  temp2 = temp2 + &
2268  (sysa(i)%sys(j)%hs(iii)**2)*sysa(i)%sys(j)%lat(iii)
2269  END DO
2270  lonmean=temp1/max(sum(sysa(i)%sys(j)%hs(1:npnts)**2),0.001)
2271  latmean=temp2/max(sum(sysa(i)%sys(j)%hs(1:npnts)**2),0.001)
2272  !070512----------- Weight averages with Hm0 ---------------------
2273  !071012----------- Grid point indexing --------------------------
2274  ALLOCATE(sysa(i)%sys(j)%indx(maxi*maxj))
2275  sysa(i)%sys(j)%indx = 9999
2276  DO iii = 1,sysa(i)%sys(j)%nPoints
2277  sysa(i)%sys(j)%indx(iii) = &
2278  (sysa(i)%sys(j)%j(iii)-1)*maxi + &
2279  sysa(i)%sys(j)%i(iii)
2280  END DO
2281  !071012----------- Grid point indexing --------------------------
2282  WRITE(20,*) 'System no. ',j,' of ',maxsys(i)
2283  WRITE(20,*) 'Size =', npnts
2284  WRITE(20,*) 'lonMean =', lonmean
2285  WRITE(20,*) 'latMean =', latmean
2286  WRITE(20,*) 'tpMean =', sysa(i)%sys(j)%tpMean
2287  WRITE(20,*) 'dirMean =', sysa(i)%sys(j)%dirMean
2288  sysa(i)%sys(j)%grp = 9999 !Now redundant?
2289 
2290  ! Compute deltas
2291  tbsysmem = sysmem(1:maxgroup)%tpMean
2292  WRITE(20,*) 'Tbsysmem(:) = ', tbsysmem(:)
2293  ! Compute deltas the same way as for field combining - they should
2294  ! be of the same degree of strictness as the latter, otherwise
2295  ! the time combining will lose track!
2296  !3stddev m1 = -3.645*Tb + 63.211
2297  !3stddev m1 = MAX(m1,10.)
2298  !3stddev m2 = -0.346*Tb + 3.686
2299  !3stddev m2 = MAX(m2,0.6)
2300  !1stddev m1 = -2.219*Tb + 35.734
2301  !1stddev m1 = MAX(m1,5.)
2302  !1stddev m2 = -0.226*Tb + 2.213
2303  !1stddev m2 = MAX(m2,0.35)
2304  !071412 m1 = -5.071*Tb + 90.688
2305  !071412 m1 = MAX(m1,16.)
2306  !071412 m2 = -0.467*Tb + 5.161
2307  !071412 m2 = MAX(m2,1.0)
2308  !071412 deltaDir = (m1*1. + dirTimeKnob)*1.
2309  !071412 deltaPer = (m2*1. + tpTimeKnob)*1.
2310  DO ii = 1,SIZE(ind2)
2311  m1sysmem(ii) = max((-3.645*tbsysmem(ii)+63.211),10.)
2312  m2sysmem(ii) = max((-0.346*tbsysmem(ii)+3.686),0.6)
2313  END DO
2314  deltadirsysmem = m1sysmem(:)*1. + dirtimeknob
2315  deltapersysmem = m2sysmem(:)*1. + tptimeknob
2316  WRITE(20,*) 'deltaDirsysmem(:) = ',deltadirsysmem
2317  WRITE(20,*) 'deltaPersysmem(:) = ',deltapersysmem
2318 
2319  ! Criterion 1: Mean period
2320  ALLOCATE( temp(SIZE(ind2)) )
2321  temp = abs( sysa(i)%sys(j)%tpMean - &
2322  sysmem(ind2(:))%tpMean )
2323  WRITE(20,*) 'tpMean list =', &
2324  sysmem(ind2(:))%tpMean
2325  WRITE(20,*) 'tpMinVal list =', temp
2326  tpminval = minval(temp)
2327  tpminind = findfirst(temp,SIZE(temp),tpminval)
2328 
2329  ! Criterion 2: Mean direction
2330  ALLOCATE( dirs(SIZE(ind2)) )
2331  dirs(:)=abs( sysa(i)%sys(j)%dirMean - &
2332  sysmem(ind2(:))%dirMean )
2333  ! Deal with wrap around
2334  DO idir = 1, SIZE(dirs)
2335  IF (dirs(idir).GE.180.) dirs(idir)=360-dirs(idir)
2336  END DO
2337  WRITE(20,*) 'dirMean list =', &
2338  sysmem(ind2(:))%dirMean
2339  WRITE(20,*) 'dirMinVal list =', dirs
2340 
2341  ! Criterion 3: Size
2342  WRITE(20,*) 'Size list =', &
2343  sysmem(ind2(:))%nPoints
2344 
2345  ! Criterion 4: Distance between systems
2346  ALLOCATE (mnlonlist(SIZE(ind2)))
2347  ALLOCATE (mnlatlist(SIZE(ind2)))
2348  ALLOCATE (mndist(SIZE(ind2)))
2349  DO ii = 1,SIZE(ind2)
2350  mnlonlist(ii) = sysmem(ind2(ii))%lonMean
2351  mnlatlist(ii) = sysmem(ind2(ii))%latMean
2352  mndist(ii) = sqrt((lonmean-mnlonlist(ii))**2 + &
2353  (latmean-mnlatlist(ii))**2)
2354  END DO
2355  dmndiag = sqrt(lonext**2+latext**2)
2356  WRITE(20,*) 'Distance list =',mndist(:)
2357  WRITE(20,*) 'Domain diagonal =',dmndiag
2358 
2359  ! Criterion 5: Overlap of systems
2360  ALLOCATE (olsize(SIZE(ind2)))
2361  DO ii = 1,SIZE(ind2)
2362 
2363  IF (sysmem(ind2(ii))%nPoints.GT.0) THEN
2364  CALL intersect(real(sysa(i)%sys(j)%indx(1:npnts)),npnts, &
2365  REAL(sysMem(ind2(ii))%indx(1:sysMem(ind2(ii))%nPoints)),&
2366  sysMem(ind2(ii))%nPoints,dummy1,olsize(ii),dummy2,dummy3)
2367  ELSE
2368  olsize(ii) = 0
2369  END IF
2370  END DO
2371 
2372  gof(j,1:SIZE(ind2)) = (temp/deltapersysmem(:))**2 + &
2373  (dirs/deltadirsysmem(:))**2 + &
2374  ! (4*mndist(:)/dmndiag)**2
2375  ( (real(olsize(:)) - &
2376  REAL(sysMem(ind2(:))%nPoints) )/&
2377  (0.50*MAX(REAL(sysMem(ind2(:))%nPoints),0.001)) )**2
2378  ! Remove GoF entries which exceed predifined tolerances
2379  DO ii = 1,SIZE(ind2)
2380  WRITE(20,*) 'Testing: ii,olsize(ii),size,frac =',&
2381  ii,olsize(ii),sysmem(ind2(ii))%nPoints,&
2382  REAL(olsize(ii))/&
2383  MAX(REAL(sysMem(ind2(ii))%nPoints),0.001)
2384  IF ( real(olsize(ii)).LT.&
2385  0.50*real(sysmem(ind2(ii))%nPoints) ) THEN
2386  gof(j,ii) = 9999.
2387  END IF
2388  IF ( (temp(ii).GT.deltapersysmem(ii)).OR.&
2389  (dirs(ii).GT.deltadirsysmem(ii)) ) THEN
2390  gof(j,ii) = 9999.
2391  END IF
2392  END DO
2393  WRITE(20,*) 'GOF(j,:) =',gof(j,:)
2394 
2395  IF (ALLOCATED(temp)) DEALLOCATE(temp)
2396  IF (ALLOCATED(dirs)) DEALLOCATE(dirs)
2397  IF (ALLOCATED(mnlonlist)) DEALLOCATE(mnlonlist)
2398  IF (ALLOCATED(mnlatlist)) DEALLOCATE(mnlatlist)
2399  IF (ALLOCATED(mndist)) DEALLOCATE(mndist)
2400  IF (ALLOCATED(olsize)) DEALLOCATE(olsize)
2401 
2402  !071212-----------GoF 2D-------------
2403  END DO
2404  IF (ALLOCATED(tbsysmem)) DEALLOCATE(tbsysmem)
2405  IF (ALLOCATED(deltadirsysmem)) DEALLOCATE(deltadirsysmem)
2406  IF (ALLOCATED(deltapersysmem)) DEALLOCATE(deltapersysmem)
2407  IF (ALLOCATED(m1sysmem)) DEALLOCATE(m1sysmem)
2408  IF (ALLOCATED(m2sysmem)) DEALLOCATE(m2sysmem)
2409 
2410  WRITE(20,*) 'GoF3:'
2411  DO jj = 1,maxsys(i)
2412  WRITE(20,*) gof(jj,:)
2413  END DO
2414 
2415  ! Find minima in GoF
2416  DO k = 1,maxgroup
2417  gofminval(k) = minval(gof(:,k))
2418  gofminind(k) = findfirst(gof(:,k),SIZE(gof,1),gofminval(k))
2419  IF (gofminval(k).EQ.9999) THEN
2420  gofminind(k) = 0
2421  END IF
2422  END DO
2423 
2424  IF (ALLOCATED(gof)) DEALLOCATE(gof)
2425 
2426  DO j = 1, maxsys(i)
2427  new = 0
2428  ! Look up sysMem match for this current system. If no match
2429  ! is found, the index value 0 is returned.
2430  tpminind = 0
2431  temp1 = 9999.
2432  DO jj = 1, SIZE(gofminind)
2433  IF (gofminind(jj).EQ.j) THEN
2434  IF (gofminval(jj).LT.temp1) THEN
2435  tpminind = jj
2436  temp1 = gofminval(jj)
2437  END IF
2438  END IF
2439  END DO
2440  dirminind = tpminind
2441  WRITE(20,*) 'System, GOFMinInd: ',j,tpminind
2442 
2443  IF (tpminind.NE.0) THEN
2444  ! Success
2445  !071212-----------GoF 2D-------------
2446 
2447  counter = counter+1
2448  sysa(i)%sys(j)%grp = &
2449  sysmem(ind2(dirminind))%grp
2450  alreadyused(counter) = sysa(i)%sys(j)%grp
2451 
2452  WRITE(20,*) 'Case 1: matched this ts (',i, &
2453  ') sys ',sysa(i)%sys(j)%sysInd,' (tp=', &
2454  sysa(i)%sys(j)%tpMean,' dir=', &
2455  sysa(i)%sys(j)%dirMean,') with grp ', &
2456  sysmem(ind2(dirminind))%grp
2457  WRITE(20,*) 'Added ',alreadyused(counter), &
2458  ' in array *alreadyUsed*'
2459  ELSE
2460  new = 1
2461  END IF
2462 
2463  IF (new.EQ.1) THEN
2464  used = 0
2465  DO k = 1, maxgroup
2466  ok = 1
2467  WRITE(20,*) 'maxGroup,k,ok,used =', &
2468  maxgroup,k,ok,used
2469  ! Make sure it hasn't been used yet (at current time level)
2470  IF ((i.GT.2).AND. &
2471  (.NOT.any(alreadyused(:).EQ.k))) THEN
2472  ! Make sure it hasn't been used yet (at previous time level)
2473  DO l = 1, maxgroup
2474  ! If last update of system was more that *6* time steps
2475  ! ago, system can be released (TO CALIBRATE)
2476  IF ( (sysmem(l)%grp.EQ.k).AND. &
2477  ((i-sysmem(l)%updated).LT.6) ) ok = 0
2478  WRITE(20,*) 'l, ok = ',l,ok
2479  END DO
2480  IF (ok.EQ.1) THEN
2481  sysa(i)%sys(j)%grp = k
2482  counter = counter+1;
2483  alreadyused(counter) = k
2484  used = 1
2485  WRITE(20,*) 'k,used,counter =', &
2486  k,used,counter
2487  EXIT
2488  END IF
2489  END IF
2490  END DO
2491  IF (used.EQ.0) THEN
2492  maxgroup = maxgroup+1
2493  sysa(i)%sys(j)%grp = maxgroup
2494  ! Increase sysMem by one slot
2495  sysmem(maxgroup)%grp = maxgroup
2496  counter = counter+1
2497  alreadyused(counter) = maxgroup
2498  END IF
2499  WRITE(20,*) 'counter,maxGroup,sysA(i)%sys(j)%grp =',&
2500  counter,maxgroup,sysa(i)%sys(j)%grp
2501  WRITE(20,*) 'NO GRP MATCH case 2'
2502  END IF
2503 
2504  END DO
2505  IF (ALLOCATED(ind)) DEALLOCATE(ind) !071212 Shifted
2506  IF (ALLOCATED(ind2)) DEALLOCATE(ind2) !071212 Shifted
2507  IF (ALLOCATED(gofminval)) DEALLOCATE(gofminval)
2508  IF (ALLOCATED(gofminind)) DEALLOCATE(gofminind)
2509 
2510  IF (ALLOCATED(alreadyused)) DEALLOCATE(alreadyused)
2511  IF (ALLOCATED(allind)) DEALLOCATE(allind)
2512 
2513  ! Update sysMem
2514  DO k = 1, maxgroup
2515  DO kk = 1, maxsys(i)
2516  IF (sysa(i)%sys(kk)%grp.EQ.sysmem(k)%grp) THEN
2517  sysmem(k)%nPoints = sysa(i)%sys(kk)%nPoints
2518  sysmem(k)%lonMean = &
2519  sum(sysa(i)%sys(kk)%lon(1:sysmem(k)%nPoints))/&
2520  sysmem(k)%nPoints
2521  sysmem(k)%latMean = &
2522  sum(sysa(i)%sys(kk)%lat(1:sysmem(k)%nPoints))/&
2523  sysmem(k)%nPoints
2524  !070512----------- Weight averages with Hm0 ---------------------
2525  temp1 = 0.
2526  temp2 = 0.
2527  DO iii = 1,sysmem(k)%nPoints
2528  temp1 = temp1 + &
2529  (sysa(i)%sys(kk)%hs(iii)**2)*sysa(i)%sys(kk)%lon(iii)
2530  temp2 = temp2 + &
2531  (sysa(i)%sys(kk)%hs(iii)**2)*sysa(i)%sys(kk)%lat(iii)
2532  END DO
2533  sysmem(k)%lonMean = temp1/&
2534  max(sum(sysa(i)%sys(kk)%hs(1:sysmem(k)%nPoints)**2),&
2535  0.001)
2536  sysmem(k)%latMean = temp2/&
2537  max(sum(sysa(i)%sys(kk)%hs(1:sysmem(k)%nPoints)**2),&
2538  0.001)
2539  !070512----------- Weight averages with Hm0 ---------------------
2540  sysmem(k)%tpMean = sysa(i)%sys(kk)%tpMean
2541  sysmem(k)%dirMean = sysa(i)%sys(kk)%dirMean
2542  !071012----------- Grid point indexing --------------------------
2543  sysmem(k)%indx(:) = 9999
2544  DO iii = 1,sysmem(k)%nPoints
2545  sysmem(k)%indx(iii) = &
2546  (sysa(i)%sys(kk)%j(iii)-1)*maxi + &
2547  sysa(i)%sys(kk)%i(iii)
2548  END DO
2549  !071012----------- Grid point indexing --------------------------
2550  sysmem(k)%updated = i
2551  sysmem(k)%length = sysmem(k)%length + 1
2552  END IF
2553  END DO
2554  !Test for expired groups
2555  IF ((i-sysmem(k)%updated).GE.6) THEN
2556  sysmem(k)%nPoints = 0
2557  sysmem(k)%lonMean = 9999.
2558  sysmem(k)%latMean = 9999.
2559  sysmem(k)%tpMean = 9999.
2560  sysmem(k)%dirMean = 9999.
2561  sysmem(k)%indx(:) = 9999
2562  sysmem(k)%updated = -9999
2563  sysmem(k)%length = 0
2564  END IF
2565  END DO
2566  !083012 !Filter out duplicates groups that can develop
2567  DO l = 1, maxgroup
2568  DO ll = (l+1), maxgroup
2569 
2570  deltadir = max((-3.645*sysmem(l)%tpMean+63.211),10.)*1.
2571  deltaper = max((-0.346*sysmem(l)%tpMean+3.686),0.6)*1.
2572 
2573  IF ( (abs(sysmem(l)%tpMean-sysmem(ll)%tpMean).LT.&
2574  deltaper).AND. &
2575  (abs(sysmem(l)%dirMean-sysmem(ll)%dirMean).LT.&
2576  deltadir).AND. &
2577  (sysmem(l)%updated.NE.sysmem(ll)%updated).AND. &
2578  (sysmem(ll)%nPoints.NE.0) ) THEN
2579  !Find the more recent entry, and delete from group
2580  IF (sysmem(ll)%length.LT.sysmem(l)%length) THEN
2581  idup = ll
2582  WRITE(20,*) 'Deleting memgroup ',ll, &
2583  '(updated',sysmem(ll)%updated,', length', &
2584  sysmem(ll)%length,'), duplicate of memgroup', &
2585  l,'(updated',sysmem(l)%updated,', length', &
2586  sysmem(l)%length,'):'
2587  ELSE
2588  idup = l
2589  WRITE(20,*) 'Deleting memgroup ',l, &
2590  '(updated',sysmem(l)%updated,', length', &
2591  sysmem(l)%length,'), duplicate of memgroup', &
2592  ll,'(updated',sysmem(ll)%updated,', length', &
2593  sysmem(ll)%length,'):'
2594  END IF
2595  WRITE(20,*) 'deltaPer, diff Per:',deltaper,&
2596  abs(sysmem(l)%tpMean-sysmem(ll)%tpMean)
2597  WRITE(20,*) 'deltaDir, diff Dir:',deltadir,&
2598  abs(sysmem(l)%dirMean-sysmem(ll)%dirMean)
2599  sysmem(idup)%nPoints = 0
2600  sysmem(idup)%lonMean = 9999.
2601  sysmem(idup)%latMean = 9999.
2602  sysmem(idup)%tpMean = 9999.
2603  sysmem(idup)%dirMean = 9999.
2604  sysmem(idup)%indx(:) = 9999
2605  sysmem(idup)%updated = -9999
2606  sysmem(idup)%length = 0
2607  END IF
2608  END DO
2609  END DO
2610  ELSE
2611  WRITE(20,*) '*** No systems at this time level. ', &
2612  'No. systems =',SIZE(sysa(i)%sys)
2613  !Test for expired groups
2614  DO k = 1, maxgroup
2615  IF ((i-sysmem(k)%updated).GE.6) THEN
2616  sysmem(k)%nPoints = 0
2617  sysmem(k)%lonMean = 9999.
2618  sysmem(k)%latMean = 9999.
2619  sysmem(k)%tpMean = 9999.
2620  sysmem(k)%dirMean = 9999.
2621  sysmem(k)%indx(:) = 9999
2622  sysmem(k)%updated = -9999
2623  sysmem(k)%length = 0
2624  END IF
2625  END DO
2626  END IF
2627  ! ******** Test output ***********************
2628  DO k = 1, maxgroup
2629  WRITE(20,*) 'sysMem(',k,')%grp =',sysmem(k)%grp
2630  WRITE(20,*) 'sysMem(',k,')%nPoints =',sysmem(k)%nPoints
2631  WRITE(20,*) 'sysMem(',k,')%lonMean =',sysmem(k)%lonMean
2632  WRITE(20,*) 'sysMem(',k,')%latMean =',sysmem(k)%latMean
2633  WRITE(20,*) 'sysMem(',k,')%tpMean =',sysmem(k)%tpMean
2634  WRITE(20,*) 'sysMem(',k,')%dirMean =',sysmem(k)%dirMean
2635  WRITE(20,*) 'sysMem(',k,')%updated =',sysmem(k)%updated
2636  WRITE(20,*) 'sysMem(',k,')%length =',sysmem(k)%length
2637  END DO
2638  ! ********************************************
2639  END DO
2640 
2641  ! Write hotfile of wave groups
2642  OPEN(unit=27,file='sys_restart1.ww3',status='unknown')
2643  WRITE(27,'(A23,I10)') 'maxGroup =',maxgroup
2644  DO k = 1, maxgroup
2645  WRITE(27,'(A8,I3,A12,I10)') 'sysMem( ',k, &
2646  ' )%grp =',sysmem(k)%grp
2647  WRITE(27,'(A8,I3,A12,I10)') 'sysMem( ',k, &
2648  ' )%nPoints =',sysmem(k)%nPoints
2649  WRITE(27,'(A8,I3,A12,F10.4)') 'sysMem( ',k, &
2650  ' )%lonMean =',sysmem(k)%lonMean
2651  WRITE(27,'(A8,I3,A12,F10.4)') 'sysMem( ',k, &
2652  ' )%latMean =',sysmem(k)%latMean
2653  WRITE(27,'(A8,I3,A12,F10.3)') 'sysMem( ',k, &
2654  ' )%tpMean =',sysmem(k)%tpMean
2655  WRITE(27,'(A8,I3,A12,F10.3)') 'sysMem( ',k, &
2656  ' )%dirMean =',sysmem(k)%dirMean
2657  WRITE(27,'(A8,I3,A12,I10)') 'sysMem( ',k, &
2658  ' )%updated =',sysmem(k)%updated
2659  WRITE(27,'(A8,I3,A12,I10)') 'sysMem( ',k, &
2660  ' )%length =',sysmem(k)%length
2661  DO j = maxj,1,-1
2662  DO i = 1,maxi
2663  WRITE(27,'(I8)',advance='NO') sysmem(k)%indx((j-1)*maxi+i)
2664  END DO
2665  WRITE(27,'(A)',advance='YES') ''
2666  END DO
2667  END DO
2668  CLOSE(27)
2669 
2670 2000 CONTINUE
2671  RETURN

References file(), findfirst(), intersect(), length(), and sort().

Referenced by wavetracking_nws_v2().

◆ union()

subroutine w3strkmd::union ( real, dimension(insize1), intent(in)  INARRAY1,
integer, intent(in)  INSIZE1,
real, dimension(insize2), intent(in)  INARRAY2,
integer, intent(in)  INSIZE2,
real, dimension(:), pointer  OUTARRAY,
integer, intent(out)  OUTSIZE 
)

Definition at line 5256 of file w3strkmd.F90.

5256  !/
5257  !/ +-----------------------------------+
5258  !/ | WAVEWATCH III NOAA/NCEP |
5259  !/ | A. J. van der Westhuysen |
5260  !/ | Jeff Hanson |
5261  !/ | Eve-Marie Devaliere |
5262  !/ | FORTRAN 95 |
5263  !/ | Last update : 4-Jan-2013 |
5264  !/ +-----------------------------------+
5265  !/
5266  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
5267  !/ by Jeff Hanson & Eve-Marie Devaliere
5268  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
5269  !/ 20-Dec-2016 : Add count-histogram method similarly
5270  !/ to INTERSECT (S. Zieger) ( version 5.16 )
5271  !/
5272  !/ Copyright 2009-2013 National Weather Service (NWS),
5273  !/ National Oceanic and Atmospheric Administration. All rights
5274  !/ reserved. WAVEWATCH III is a trademark of the NWS.
5275  !/ No unauthorized use without permission.
5276  !/
5277  IMPLICIT NONE
5278  !
5279  ! 1. Purpose :
5280  !
5281  ! (i) Returns the union of INARRAY1 and INARRAY2.
5282  ! (ii) Sort the resulting array in ascending order.
5283  !
5284  ! 2. Method
5285  !
5286  ! 3. Parameters :
5287  !
5288  ! Parameter list
5289  ! ----------------------------------------------------------------
5290  ! INARRAY REAL ARR input Input array
5291  ! INSIZE INTEGER input Size of input array
5292  ! OUTARRAY REAL ARR output Output array (sorted)
5293  ! OUTSIZE INTEGER output Size of output array (number of
5294  ! unique elements)
5295  INTEGER :: INSIZE1, INSIZE2, OUTSIZE
5296  REAL :: INARRAY1(INSIZE1), INARRAY2(INSIZE2)
5297  REAL, POINTER :: OUTARRAY(:)
5298  !
5299  INTENT (IN) inarray1, insize1, inarray2, insize2
5300  INTENT (OUT) outsize
5301  !
5302  ! Local variables
5303  ! ----------------------------------------------------------------
5304  ! VIDX1, VIDX2 - array(s) in which the value is represented by
5305  ! its index (i.e. histogram with frequency 1)
5306  ! N - data range and size of possible intersections.
5307  !
5308  LOGICAL,ALLOCATABLE :: VIDX1(:),VIDX2(:)
5309  INTEGER,ALLOCATABLE :: IPOS1(:),IPOS2(:)
5310  REAL,ALLOCATABLE :: TEMP(:)
5311  !
5312  INTEGER :: I, J
5313  INTEGER :: N, IMIN, IMAX
5314  INTEGER :: MINV1,MAXV1, MINV2, MAXV2
5315  !
5316  ! 4. Subroutines used :
5317  !
5318  ! Name Type Module Description
5319  ! ----------------------------------------------------------------
5320  ! QSORT Subr. Private Quicksort algorithm
5321  !
5322  ! 5. Subroutines calling
5323  !
5324  ! combineSys
5325  !
5326  ! 6. Error messages :
5327  !
5328  ! 7. Remarks :
5329  !
5330  ! 8. Structure :
5331  !
5332  ! -
5333  !
5334  ! 9. Switches :
5335  !
5336  ! None defined yet.
5337  !
5338  ! 10. Source code :
5339  !
5340  !/ ------------------------------------------------------------------- /
5341  !/ --- Setup input arrays. ---
5342  IF ( (insize1+insize2).EQ.0 ) THEN
5343  outsize = 0
5344  ALLOCATE(outarray(outsize))
5345 
5346  ELSEIF ( insize1.EQ.0 ) THEN
5347  outsize = insize2
5348  ALLOCATE(outarray(outsize))
5349  ALLOCATE(temp(outsize))
5350 
5351  DO i=1,outsize
5352  outarray(i) = inarray2(i)
5353  temp(i) = real(i)
5354  END DO
5355  CALL qsort(outarray,temp,1,outsize)
5356 
5357  ELSEIF ( insize2.EQ.0 ) THEN
5358  outsize = insize1
5359  ALLOCATE(outarray(outsize),temp(outsize))
5360 
5361  DO i=1,outsize
5362  outarray(i) = inarray1(i)
5363  temp(i) = real(i)
5364  END DO
5365  CALL qsort(outarray,temp,1,outsize)
5366 
5367  ELSE
5368  outsize = 0
5369  !/ --- Calculate the range of the two sets. ---
5370  minv1 = int(minval(inarray1))
5371  maxv1 = int(maxval(inarray1))
5372  minv2 = int(minval(inarray2))
5373  maxv2 = int(maxval(inarray2))
5374  !
5375  !/ --- Allow extra elementes: ZERO, and make sure index is 1:N. ---
5376  imin = min(minv1,minv2)-1
5377  imax = max(maxv1,maxv2)+1
5378 
5379  n = imax-imin
5380 
5381  ALLOCATE(vidx1(n),vidx2(n))
5382  ALLOCATE(ipos1(n),ipos2(n))
5383 
5384  vidx1(1:n) = .false.
5385  vidx2(1:n) = .false.
5386  ipos1(1:n) = -9999
5387  ipos2(1:n) = -9999
5388  !/
5389  DO i=1,insize1
5390  j = int(inarray1(i)-imin)
5391  IF ( .NOT.vidx1(j) ) THEN
5392  outsize = outsize + 1
5393  vidx1(j) = .true.
5394  ipos1(j) = i
5395  END IF
5396  END DO
5397 
5398  DO i=1,insize2
5399  j = int(inarray2(i)-imin)
5400  IF ( .NOT.vidx1(j).AND..NOT.vidx2(j) ) THEN
5401  outsize = outsize + 1
5402  vidx2(j) = .true.
5403  ipos2(j) = i
5404  END IF
5405  END DO
5406 
5407  ALLOCATE(outarray(outsize))
5408 
5409  i = 1
5410  DO j=1,n
5411  IF ( vidx1(j).AND.i.LE.outsize ) THEN
5412  outarray(i) = inarray1(ipos1(j))
5413  i = i + 1
5414  ELSEIF ( vidx2(j).AND.i.LE.outsize ) THEN
5415  outarray(i) = inarray2(ipos2(j))
5416  i = i + 1
5417  END IF
5418  END DO
5419 
5420  DEALLOCATE(vidx1,vidx2)
5421  DEALLOCATE(ipos1,ipos2)
5422 
5423  END IF
5424  !/
5425  RETURN
5426  !/

References qsort().

Referenced by combinesys().

◆ unique()

subroutine w3strkmd::unique ( real, dimension(insize), intent(in)  INARRAY,
integer, intent(in)  INSIZE,
real, dimension(:), pointer  OUTARRAY,
integer, intent(out)  OUTSIZE 
)

Definition at line 4686 of file w3strkmd.F90.

4686  !/
4687  !/ +-----------------------------------+
4688  !/ | WAVEWATCH III NOAA/NCEP |
4689  !/ | A. J. van der Westhuysen |
4690  !/ | Jeff Hanson |
4691  !/ | Eve-Marie Devaliere |
4692  !/ | FORTRAN 95 |
4693  !/ | Last update : 22-Dec-2016 |
4694  !/ +-----------------------------------+
4695  !/
4696  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
4697  !/ by Jeff Hanson & Eve-Marie Devaliere
4698  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
4699  !/ 12-Dec-2016 : Change algorithm from N*N to N*log(N)
4700  !/ (S. Zieger BoM Australia) ( version 5.16 )
4701  !/
4702  !/ Copyright 2009-2013 National Weather Service (NWS),
4703  !/ National Oceanic and Atmospheric Administration. All rights
4704  !/ reserved. WAVEWATCH III is a trademark of the NWS.
4705  !/ No unauthorized use without permission.
4706  !/
4707  IMPLICIT NONE
4708  !
4709  ! 1. Purpose :
4710  !
4711  ! Returns the sorted elements that are unique in INARRAY.
4712  !
4713  ! 2. Method
4714  !
4715  ! 1. Sort input array with quicksort
4716  ! 2. Copy sequential-elements if the 'current' element
4717  ! is not equal to the 'previous' element in array.
4718  !
4719  ! 3. Parameters :
4720  !
4721  ! Parameter list
4722  ! ----------------------------------------------------------------
4723  ! INARRAY REAL ARR input Input array
4724  ! INSIZE INTEGER input Size of input array
4725  ! OUTARRAY REAL ARR output Output array (sorted)
4726  ! OUTSIZE INTEGER output Size of output array (number of unique elements)
4727  !
4728  INTEGER, INTENT(IN) :: INSIZE
4729  INTEGER, INTENT(OUT) :: OUTSIZE
4730  REAL, INTENT(IN) :: INARRAY(INSIZE)
4731  REAL, POINTER :: OUTARRAY(:)
4732  !
4733  ! Local variables
4734  ! ----------------------------------------------------------------
4735  INTEGER :: I, K
4736  REAL :: ARRAY(INSIZE), TEMP(INSIZE)
4737  !
4738  ! 4. Subroutines used :
4739  !
4740  ! Name Type Scope Description
4741  ! ----------------------------------------------------------------
4742  ! QSORT Subr. Private Quicksort algorithm
4743  !
4744  ! 5. Subroutines calling
4745  !
4746  ! waveTracking_NWS_V2
4747  ! findSys
4748  ! printFinalSys
4749  ! combineSys
4750  ! findIJV4
4751  !
4752  ! 6. Error messages :
4753  !
4754  ! 7. Remarks :
4755  !
4756  ! 8. Structure :
4757  !
4758  ! -
4759  !
4760  ! 9. Switches :
4761  !
4762  ! None defined yet.
4763  !
4764  ! 10. Source code :
4765  !
4766  !/ ------------------------------------------------------------------- /
4767  k = 1
4768 
4769  IF ( insize.EQ.0 ) THEN
4770  WRITE(20,*) '*** In Subr. UNIQUE: Input array has length=0!'
4771  ELSE
4772  !/ --- Setup input arrays and temporary arrays. ---
4773  DO i=1,insize
4774  array(i) = inarray(i)
4775  temp(i) = real(i)
4776  END DO
4777  !/
4778  !/ --- Sort input arrays (use temporary array to store indices). ---
4779  CALL qsort(array,temp,1,insize)
4780  !/
4781  !/ --- Reset temporary array. ---
4782  temp(:) = 9999.
4783  !/
4784  !/ --- Initialise first values and array index. ---
4785  k = 1
4786  temp(k) = array(k)
4787  k = k + 1
4788  !/ --- Iterate over elements in array. ---
4789  DO i=2,insize
4790  !/ --- Compare sequential array values ('previous' less than 'next')
4791  !/ and test against the last list element check in. ---
4792  IF ( array(i).GT.array(i-1) .AND. &
4793  array(i).GT.temp(k-1) ) THEN
4794  temp(k) = array(i)
4795  k = k + 1
4796  END IF
4797  END DO
4798 
4799  !/ --- Allocate output array ---
4800  outsize = k - 1
4801  ALLOCATE(outarray(outsize))
4802  !/ --- Transfer output from temporary array to output array. ---
4803  IF ( outsize.GE.1 ) THEN
4804  DO i=1,outsize
4805  outarray(i) = temp(i)
4806  END DO
4807  END IF
4808  END IF
4809  !/
4810  RETURN
4811  !/

References qsort().

Referenced by combinesys(), findijv4(), findsys(), printfinalsys(), setdiff(), and wavetracking_nws_v2().

◆ wavetracking_nws_v2()

subroutine w3strkmd::wavetracking_nws_v2 ( integer, intent(in)  intype,
integer, intent(in)  tmax,
integer, intent(in)  tcur,
character, intent(in)  filename,
real*8  tstart,
real*8  tend,
real  dt,
integer  ntint,
real, intent(in)  minlon,
real, intent(in)  maxlon,
real, intent(in)  minlat,
real, intent(in)  maxlat,
integer  mxcwt,
integer  mycwt,
real, intent(in)  dirKnob,
real, intent(in)  perKnob,
real, intent(in)  hsKnob,
real, intent(in)  wetPts,
real, intent(in)  seedLat,
real, intent(in)  seedLon,
real, intent(in)  dirTimeKnob,
real, intent(in)  tpTimeKnob,
character, intent(in)  paramFile,
type(timsys), dimension(:), pointer  sysA,
type(dat2d), dimension(:), pointer  wsdat,
integer, dimension(:), pointer  maxSys,
integer, intent(out)  maxGroup 
)

042916 IF ( (llat(l).EQ.mlat(i,j)).AND. & 042916 (llon(l).EQ.mlon(i,j)) ) THEN

Definition at line 298 of file w3strkmd.F90.

298  !/
299  !/ +-----------------------------------+
300  !/ | WAVEWATCH III NOAA/NCEP |
301  !/ | A. J. van der Westhuysen |
302  !/ | Jeff Hanson |
303  !/ | Eve-Marie Devaliere |
304  !/ | FORTRAN 95 |
305  !/ | Last update : 4-Jan-2013 |
306  !/ +-----------------------------------+
307  !/
308  !/ 03-Feb-2012 : Origination, based on Matlab code ( version 4.05 )
309  !/ by Jeff Hanson & Eve-Marie Devaliere
310  !/ 04-Jan-2013 : Inclusion in trunk ( version 4.08 )
311  !/
312  !/ Copyright 2009-2013 National Weather Service (NWS),
313  !/ National Oceanic and Atmospheric Administration. All rights
314  !/ reserved. WAVEWATCH III is a trademark of the NWS.
315  !/ No unauthorized use without permission.
316  !/
317  IMPLICIT NONE
318 #ifdef W3_MPI
319 
320  include "mpif.h"
321 #endif
322  !
323  ! 1. Purpose :
324  !
325  ! Main subroutine of spatial and temporal tracking algorithm
326  !
327  ! 2. Method
328  !
329  ! (1) Read the raw partitioning output from one of two file formats:
330  ! (a) "partRes" format of IFP-SWAN (intype=1), or
331  ! (b) WW3 spectral bulletin format (intype=2).
332  ! If intype=0, the partition data is read from memory (not activated yet).
333  !
334  ! (2) Perform tracking in space by calling subroutine spiralTrackV3
335  ! (3) Perform tracking in time by calling subroutine timeTrackingV2
336  !
337  ! 3. Parameters :
338  !
339  ! Parameter list
340  ! ----------------------------------------------------------------
341  ! intype Int input For coupling: Type of input (0 = memory; 1 = partRes file; 2 = WW3 part file)
342  ! tmax Int input For coupling: Value of maxTs to apply (1 or 2)
343  ! tcur Int input For coupling: Index of current time step (1 or 2)
344  ! filename Char input File name of locally partitioned data output
345  ! tstart Char input Start time in raw partition file (if used)
346  ! tend Char input End time in raw partition file (if used)
347  ! minlon Real input Lower lon boundary of domain to be processed
348  ! maxlon Real input Upper lon boundary of domain to be processed
349  ! minlat Real input Lower lat boundary of domain to be processed
350  ! maxlat Real input Upper lat boundary of domain to be processed
351  ! dirKnob Real input Parameter in direction for combining fields in space
352  ! perKnob Real input Parameter in period for combining fields in space
353  ! hsKnob Real input Parameter in wave height for purging fields
354  ! wetPts Real input Percentage of wet points for purging fields (fraction)
355  ! seedLat Real input Start Lat for tracking spiral (if =0 centre of field is used)
356  ! seedLon Real input Start Lon for tracking spiral (if =0 centre of field is used)
357  ! dirTimeKnob Real input Parameter in direction for combining fields in time
358  ! tpTimeKnob Real input Parameter in period for combining fields in time
359  ! paramFile Char input File name of partitioning parameters Is this used???
360  ! sys TYPE(timsys) output Final set of spatially and temporally tracked systems
361  ! wsdat TYPE(dat2d) output Final version of 2D (gridded) partition data
362  ! maxGroup Int output Maximum number of wave systems ("groups") tracked in time
363  !
364  CHARACTER :: filename*50, paramFile*32
365  REAL :: dirKnob, perKnob, hsKnob, wetPts, seedLat, &
366  seedLon, dirTimeKnob, tpTimeKnob
367  real*8 :: tstart, tend
368  INTEGER :: maxGroup, intype, tmax, tcur, ntint
369  INTEGER, POINTER :: maxSys(:)
370  TYPE(dat2d), POINTER :: wsdat(:)
371  TYPE(timsys), POINTER :: sysA(:), sysAA(:)
372  INTEGER :: NumConsSys, iConsSys
373  REAL :: dt
374  REAL :: minlon, maxlon, minlat, maxlat
375  INTEGER :: mxcwt, mycwt
376 
377  ! Note: Variables wsdat, sysA and maxSys have IN/OUT intent so that they
378  ! can be manipulated outside of this subroutine, e.g. re-indexing of
379  ! systems and groups during the simulation.
380  INTENT (IN) intype, tmax, tcur, filename, paramfile, &
381  minlon, maxlon, minlat, maxlat, &
382  hsknob, wetpts, seedlat, seedlon, &
383  dirknob, perknob, dirtimeknob, tptimeknob
384  INTENT (OUT) maxgroup
385  ! INTENT (IN OUT) wsdat, sysA, maxSys
386  !
387  ! Local variables
388  ! ----------------------------------------------------------------
389  ! llat Real Latitude of partition point, from input file
390  ! llon Real Longitude of partition point, from input file
391  ! ts Real Time step of partition, from input file
392  ! hs0 Real Wave height of partition, from input file
393  ! tp0 Real Peak period of partition, from input file
394  ! dir0 Real Mean direction of partition, from input file
395  ! dspr0 Real Mean directional spread of partition, from input file
396  ! wf0 Real wind fraction of partition, from input file (removed)
397  ! wndSpd0 Real Wind speed of partition, from input file
398  ! wndDir0 Real Wind direction of partition, from input file
399  ! wndFce0 Real Wind force of partition, from input file (not, used; removed)
400  ! tss Int. Time step counter
401  ! t0 Int Index of first time step to compute
402  !
403  LOGICAL :: file_exists, FLFORM, LOOP
404  LOGICAL :: testout
405  parameter(testout = .false.)
406  CHARACTER :: dummy*10, dummyc*12
407  CHARACTER(LEN=10) :: VERPRT
408  CHARACTER(LEN=35) :: IDSTR
409  CHARACTER(LEN=78) :: headln1
410  CHARACTER(LEN=51) :: headln2
411  INTEGER :: line
412  INTEGER, ALLOCATABLE :: ts(:), tmp_i4(:)
413  REAL, ALLOCATABLE :: llat(:),llon(:),hs0(:), &
414  tp0(:),dir0(:),dspr0(:),&
415  wndSpd0(:),wndDir0(:)
416  real*8, ALLOCATABLE :: date0(:),tmp_r8(:)
417  INTEGER :: maxTs, t0, nout1, nout2, maxI, maxJ
418  REAL, ALLOCATABLE :: mlon(:,:), mlat(:,:), tmp_r4(:)
419  REAL, POINTER :: uniqueTim(:),uniqueLatraw(:),uniqueLonraw(:), &
420  uniqueLat(:),uniqueLon(:)
421  INTEGER :: ioerr,ierr, i, j, k, l, alreadyIn, ok, tss, tsA
422  INTEGER :: maxPart, DATETIME(2)
423  INTEGER :: tstep, iline, numpart, skipln, readln, filesize
424  REAL :: x,y,wnd,wnddir
425  REAL :: invar1, invar2, invar3, invar4
426  REAL :: invar5, invar6, invar7
427  REAL, ALLOCATABLE :: phs(:),ptp(:),pdir(:),pspr(:),pwf(:) ! current partition values
428  real*8 :: date1, date2, ttest, ttemp
429  INTEGER :: ic, leng, maxpartout ! Remove?
430  REAL :: dx
431  INTEGER :: latind1, latind2, lonind1, lonind2
432  REAL :: lonext, latext
433 
434 #ifdef W3_MPI
435  INTEGER :: rank, irank, nproc, EXTENT, DOMSIZE, tag1, tag2
436  ! INTEGER :: MPI_INT_DOMARR, MPI_REAL_DOMARR
437  INTEGER :: MPI_STATUS(MPI_STATUS_SIZE)
438  INTEGER :: REQ(16)
439  ! INTEGER :: ISTAT(MPI_STATUS_SIZE,16)
440  REAL :: COMMARR1(44)
441  INTEGER :: COMMARR2(11)
442 #endif
443  !
444  ! 4. Subroutines used :
445  !
446  ! Name Type Module Description
447  ! ----------------------------------------------------------------
448  ! UNIQUE
449  ! spiralTrackV3
450  ! timeTrackingV2
451  !
452  ! 5. Subroutines calling
453  !
454  ! WW3_SYSTRK (main program)
455  !
456  ! 6. Error messages :
457  !
458  ! 7. Remarks :
459  !
460  ! 8. Structure :
461  !
462  ! See above
463  !
464  ! 9. Switches :
465  !
466  ! None defined yet.
467  !
468  ! 10. Source code :
469  !
470  !/ ------------------------------------------------------------------- /
471 
472 #ifdef W3_MPI
473  CALL mpi_comm_rank(mpi_comm_world, rank, ierr)
474  CALL mpi_comm_size(mpi_comm_world, nproc, ierr)
475 #endif
476  NULLIFY( sysa )
477  NULLIFY( maxsys )
478 
479  ! Select input type for raw partitioning data
480  IF ((intype.EQ.1).OR.(intype.EQ.2)) THEN
481  ! Raw partitioning data is coming from an input file.
482  ! Read file here, and set up 2d array wsdat with the data.
483  t0 = 1
484  IF (intype.EQ.1) THEN
485 #ifdef W3_MPI
486  IF (rank.EQ.0) THEN
487 #endif
488  ! Read partRes format file
489  WRITE(20,*) 'Reading partRes partitioning file...'
490  filesize = 7500000
491  ALLOCATE(ts(filesize))
492  ALLOCATE(llat(filesize))
493  ALLOCATE(llon(filesize))
494  ALLOCATE(hs0(filesize))
495  ALLOCATE(tp0(filesize))
496  ALLOCATE(dir0(filesize))
497  ALLOCATE(dspr0(filesize))
498  ! ALLOCATE(wf0(filesize))
499  ALLOCATE(wndspd0(filesize))
500  ALLOCATE(wnddir0(filesize))
501  ALLOCATE(date0(filesize))
502  WRITE(20,*) '*** Max number of lines read from "partRes" ', &
503  'input file is = ',filesize,'!'
504  WRITE(6,*) 'Reading partRes file...'
505  INQUIRE(file=filename, exist=file_exists)
506  IF (.NOT.file_exists) THEN
507  WRITE(20,2001)
508  WRITE(6,2001)
509  stop 1
510  END IF
511  OPEN(unit=11,file=filename,status='old')
512  line = 1
513  DO WHILE (.true.)
514  READ (11, *, END=113) dummyc,llat(line),llon(line), &
515  ts(line),hs0(line),tp0(line),dir0(line), &
516  wndspd0(line),wnddir0(line),invar7
517  !partRes file does not contain the dspr variable
518  dspr0(line) = 9999.
519  ! wf0(line) = 9999.
520  line = line+1
521  ENDDO
522 113 ierr = -1
523  CLOSE(11)
524  line = line-1
525  WRITE(6,*) '... finished'
526  ! DEALLOCATE(date0)
527 #ifdef W3_MPI
528  END IF
529 #endif
530  ELSE IF (intype.EQ.2) THEN
531 #ifdef W3_MPI
532  IF (rank.EQ.0) THEN
533 #endif
534  ! Read WW3 Spectral Partition format file
535  ! Query input file to determine required array sizes
536  INQUIRE(file=filename, exist=file_exists)
537  IF (.NOT.file_exists) THEN
538  WRITE(20,2001)
539  WRITE(6,2001)
540  stop 1
541  END IF
542  !/ -------------------------------------------------
543  !/ Test unformatted read
544  !/ -------------------------------------------------
545  OPEN(unit=11,file=filename,form='UNFORMATTED', convert=file_endian,status='OLD',access='STREAM')
546  READ(11,err=802,iostat=ioerr) i
547  CLOSE(11)
548  !/ --- First four-byte integer could possibly be byte-swapped,
549  ! if ww3_shel was compiled on a different architecture. ---
550  k = swapi4(i)
551  flform = .NOT.(i.EQ.(len(idstr)+len(verprt)).OR.&
552  k.EQ.(len(idstr)+len(verprt)) )
553  ! ======== COUNT LOOP ===========
554  IF (flform) THEN
555  ! Input file in formatted ASCII
556  WRITE(6,*) 'Reading formatted ASCII file...'
557  OPEN(unit=11,file=filename,status='old')
558  READ(11,'(78A)') headln1
559  idstr = headln1(1:len(idstr))
560  READ(11,'(78A)') headln1
561  READ(11,'(51A)') headln2
562  ELSE
563  IF (k.EQ.(len(idstr)+len(verprt))) THEN
564  !/ --- Stop here. The file appears to be endian encoded
565  ! different from the native machine format. And, the
566  ! compiler option will override support for FORTRAN
567  ! convert statements convert=file_endian or
568  ! convert='little_endian'. ---
569  WRITE(20,1200)
570  WRITE(6,1200)
571  stop 1
572  ELSE
573  ! Input file in unformatted binary
574  WRITE(6,*) 'Reading binary formatted file...'
575  OPEN(unit=11,file=filename,form='UNFORMATTED', convert=file_endian, &
576  status='OLD')
577  ENDIF
578  rewind(11)
579  READ(11,err=802,iostat=ioerr) idstr,verprt
580  READ(11,err=802,iostat=ioerr) headln1
581  READ(11,err=802,iostat=ioerr) headln2
582  END IF
583  !/
584  IF (idstr(1:9).ne.'WAVEWATCH') THEN
585  CLOSE(11)
586  WRITE(20,1300)
587  WRITE(6,1300)
588  stop 1
589  ENDIF
590  !/ -------------------------------------------------
591  !/ Skip to start time
592  !/ -------------------------------------------------
593  skipln = 3
594  ttest = 0
595  DO WHILE (ttest.LT.tstart)
596  IF (flform) THEN
597  READ (11,1000,err=802,END=112) date1,date2,x,y, &
598  numpart,wnd,wnddir,invar6,invar7
599 #ifdef W3_del
600  write(*,*) '0:',x,y,numpart
601 #endif
602  skipln = skipln+1
603  ELSE
604  READ (11,err=802,iostat=ioerr) datetime,x,y, &
605  dummy,numpart,invar1,wnd,wnddir, &
606  invar5,invar6
607  ! write(*,*) '0:',DATETIME,numpart
608  date1=dble(datetime(1))
609  date2=dble(datetime(2))
610  END IF
611  ttest = date1 + date2*1.0e-6
612  IF (flform) THEN
613  DO line = 1,numpart+1
614  READ(11,1010,END=111,ERR=802,IOSTAT=IOERR) &
615  invar1,invar2,invar3,invar4
616  ! write(*,*) '0+:',line,numpart+1,invar1,invar2,invar3,invar4
617  skipln = skipln+1
618  END DO
619  ELSE
620  DO line = 1,numpart+1
621  READ (11,err=802,iostat=ioerr) iline,invar1, &
622  invar2,invar3,invar4,invar5,invar6
623  ! write(*,*) '0+:',line,iline,invar1,invar2,invar3,invar4,invar5,invar6
624  END DO
625  END IF
626  END DO
627  skipln = skipln-numpart-1-1
628  !/ -------------------------------------------------
629  ! Read file for ntint time levels
630  !/ -------------------------------------------------
631  readln = numpart
632  tstep = 1
633  ttemp = tstart
634  maxpart = numpart
635  DO WHILE (tstep.LE.ntint)
636  IF (readln.GT.0) THEN
637  IF (flform) THEN
638  READ (11,1000,err=802,END=111) date1,date2,x,y, &
639  numpart,wnd,wnddir,invar6,invar7
640  ELSE
641  READ (11,END=111,ERR=802,IOSTAT=IOERR) DATETIME, &
642  x,y,dummy,numpart,wnd,wnddir,invar5,invar6,invar7
643  ! write(*,*) '1:',numpart,x,y
644  date1=dble(datetime(1))
645  date2=dble(datetime(2))
646  END IF
647  maxpart = max(maxpart,numpart)
648  END IF
649 
650  ttest = date1 + date2*1.e-6
651  IF (ttest.GT.ttemp) THEN
652  tstep = tstep+1
653  ttemp = ttest
654  IF (tstep.GT.ntint) EXIT
655  END IF
656  IF (flform) THEN
657  DO line = 1,numpart+1
658  READ (11,1010,END=111,ERR=802,IOSTAT=IOERR) &
659  invar1,invar2,invar3,invar4
660 #ifdef W3_del
661  write(*,'(A,2I6,4F7.2)') '1+:',line,numpart+1,invar1,invar2,invar3,invar4
662 #endif
663  readln = readln+1
664  END DO
665  ELSE
666  DO line = 1,numpart+1
667  READ (11,END=111,ERR=802,IOSTAT=IOERR) iline,invar1,&
668  invar2,invar3,invar4,invar5,invar6
669  readln = readln+1
670  END DO
671  END IF
672  ENDDO
673 111 CONTINUE
674  CLOSE(11)
675  ! ===== END COUNT LOOP =====
676  ! ===== START READ LOOP =====
677  ALLOCATE(ts(readln))
678  ALLOCATE(llat(readln))
679  ALLOCATE(llon(readln))
680  ALLOCATE(hs0(readln))
681  ALLOCATE(tp0(readln))
682  ALLOCATE(dir0(readln))
683  ALLOCATE(dspr0(readln))
684  ! ALLOCATE(wf0(readln))
685  ALLOCATE(wndspd0(readln))
686  ALLOCATE(wnddir0(readln))
687  ALLOCATE(date0(readln))
688  ts(1:readln) = -1
689  llat(1:readln) = 9999.
690  llon(1:readln) = 9999.
691  hs0(1:readln) = 9999.
692  tp0(1:readln) = 9999.
693  dir0(1:readln) = 9999.
694  dspr0(1:readln) = 9999.
695 
696 
697  IF (flform) THEN
698  OPEN(unit=11,file=filename,status='old')
699  ELSE
700  OPEN(unit=11,file=filename,status='old', &
701  form='unformatted', convert=file_endian)
702  END IF
703  line = 1
704  tstep = 1
705  !/ -------------------------------------------------
706  !/ Skip to start time
707  !/ -------------------------------------------------
708  IF (flform) THEN
709  DO i = 1,skipln
710  READ (11, *)
711  END DO
712  ELSE
713  ! --- Repeat from above since access='DIRECT'
714  ! does not support fseek and ftell. ---
715  READ(11,END=112,ERR=802,IOSTAT=IOERR) IDSTR,verprt
716  READ(11,END=112,ERR=802,IOSTAT=IOERR) headln1
717  READ(11,END=112,ERR=802,IOSTAT=IOERR) headln2
718  !/ --- allocate buffer for all partition parameters
719  !/ for a single grid point ---
720  IF (.NOT.ALLOCATED(phs)) ALLOCATE(phs(maxpart))
721  IF (.NOT.ALLOCATED(ptp)) ALLOCATE(ptp(maxpart))
722  IF (.NOT.ALLOCATED(pdir)) ALLOCATE(pdir(maxpart))
723  IF (.NOT.ALLOCATED(pspr)) ALLOCATE(pspr(maxpart))
724  IF (.NOT.ALLOCATED(pwf)) ALLOCATE(pwf(maxpart))
725 
726  ttest = 0
727 
728  DO WHILE (ttest.LT.tstart)
729  READ (11,END=112,ERR=802,IOSTAT=IOERR) DATETIME, &
730  invar1,invar2,dummy,numpart,invar3, &
731  invar4,invar5,invar6,invar7
732  date1=dble(datetime(1))
733  date2=dble(datetime(2))
734  ttest = date1 + date2*1.0e-6
735  !/ --- reset buffer ---
736  phs(:) = 0.
737  ptp(:) = 0.
738  pdir(:) = 0.
739  pspr(:) = 0.
740  pwf(:) = 0.
741 
742  !/ --- fill buffer with partition data ---
743  READ (11,END=112,ERR=802,IOSTAT=IOERR) iline,invar1, &
744  invar2,invar3,invar4,invar5,invar6
745  DO i = 1,numpart
746  READ (11,END=112,ERR=802,IOSTAT=IOERR) iline, &
747  phs(i),ptp(i),invar3,pdir(i),pspr(i),pwf(i)
748  END DO
749  END DO
750  !/ --- move buffer content to data array ---
751  DO i=1,numpart
752  hs0(line) = phs(i)
753  tp0(line) = ptp(i)
754  dir0(line) = pdir(i)
755  dspr0(line) = pspr(i)
756  date0(line) = date1 + date2*1.0e-6
757  ts(line) = tstep
758  llat(line) = x
759  llon(line) = y
760  wndspd0(line) = wnd
761  wnddir0(line) = wnddir
762 
763  line = line + 1
764  END DO
765 
766  END IF
767  !/ -------------------------------------------------
768  ! Read file for ntint time levels
769  !/ -------------------------------------------------
770  ttemp = tstart
771  DO WHILE (line.LE.readln)
772  IF (flform) THEN
773  READ (11,1000,END=112) date1,date2,x,y,numpart, &
774  wnd,wnddir,invar6,invar7
775  ELSE
776  READ (11,err=802,iostat=ioerr) datetime,x,y, &
777  dummy,numpart,wnd,wnddir,invar5,invar6,invar7
778  date1=dble(datetime(1))
779  date2=dble(datetime(2))
780  END IF
781 
782  ttest = date1 + date2*1.0e-6
783  IF (ttest.GT.ttemp) THEN
784  tstep = tstep+1
785  ttemp = ttest
786  IF (tstep.GT.ntint) EXIT
787  END IF
788 
789  IF (flform) THEN
790  READ (11,1010,END=112) invar1,invar2,invar3,invar4 ! Skip total integral parameters
791  DO i = 1,numpart
792  IF (line.LE.readln) THEN
793  READ (11,1010,END=112) hs0(line),tp0(line), &
794  dir0(line),dspr0(line)
795  date0(line) = ttest
796 
797  ts(line) = tstep
798  llat(line) = x
799  llon(line) = y
800  wndspd0(line) = wnd
801  wnddir0(line) = wnddir
802 
803  line = line+1
804  END IF
805  END DO
806  ELSE
807  READ (11,err=802,iostat=ioerr) k,invar1,invar2, &
808  invar3,invar4,invar5
809  DO i = 1,numpart
810  IF (line.LE.readln) THEN
811  READ (11,END=112,ERR=802,IOSTAT=IOERR) k, &
812  hs0(line),tp0(line),invar3,dir0(line), &
813  dspr0(line)
814  date0(line) = ttest
815 
816  ts(line) = tstep
817  llat(line) = x
818  llon(line) = y
819  wndspd0(line) = wnd
820  wnddir0(line) = wnddir
821 
822  line = line+1
823  END IF
824  END DO
825  END IF
826  END DO
827 110 ierr = -1
828  CLOSE(11)
829 
830 112 CONTINUE
831  IF (line.EQ.1) THEN
832  WRITE(20,2002)
833  WRITE(6,2002)
834  stop 1
835  END IF
836  CLOSE(11)
837  ! ===== READ LOOP FINISHED =====
838  line=line-1
839 
840  WRITE(6,*) '... finished'
841 
842  IF (ttest.LT.tstart) THEN
843  WRITE(20,2003) tstart
844  WRITE(6,2003) tstart
845  stop 1
846  END IF
847 
848  IF (ALLOCATED(phs)) DEALLOCATE(phs)
849  IF (ALLOCATED(ptp)) DEALLOCATE(ptp)
850  IF (ALLOCATED(pdir)) DEALLOCATE(pdir)
851  IF (ALLOCATED(pspr)) DEALLOCATE(pspr)
852  IF (ALLOCATED(pwf)) DEALLOCATE(pwf)
853 
854 #ifdef W3_MPI
855  END IF
856 #endif
857  END IF
858 
859 #ifdef W3_MPI
860  IF (rank.EQ.0) THEN
861 #endif
862 
863  ! Find unique time steps (and sort in ascending order)
864  CALL unique(real(ts(1:line)),line,uniquetim,maxts)
865 
866  ! Find unique lat and lon values (and sort in ascending order)
867  CALL unique(llat(1:line),SIZE(llat(1:line)),uniquelatraw,nout1)
868  CALL unique(llon(1:line),SIZE(llon(1:line)),uniquelonraw,nout2)
869 
870  !--042916-----------------------
871  !
872  ! Redefine uniqueLatraw and uniqueLonrawto based on domain extent
873  WRITE(20,*) 'uniqueLatraw(:) =', uniquelatraw(:)
874  WRITE(20,*) 'uniqueLonraw(:) =', uniquelonraw(:)
875 
876  WRITE(20,*) 'No. increments: Longitude, Latitue =', mxcwt, mycwt
877  DEALLOCATE(uniquelatraw)
878  DEALLOCATE(uniquelonraw)
879  ALLOCATE(uniquelatraw(mycwt+1))
880  ALLOCATE(uniquelonraw(mxcwt+1))
881  DO i = 1,(mycwt+1)
882  uniquelatraw(i) = minlat + &
883  (real(i)-1)/real(mycwt)*(maxlat-minlat)
884  END DO
885  DO i = 1,(mxcwt+1)
886  uniquelonraw(i) = minlon + &
887  (real(i)-1)/real(mxcwt)*(maxlon-minlon)
888  END DO
889  WRITE(20,*) 'uniqueLatraw(:) =', uniquelatraw(:)
890  WRITE(20,*) 'uniqueLonraw(:) =', uniquelonraw(:)
891  !
892  !--042916-----------------------
893 
894  ! Filter out lats and lons outside of domain of interest
895  DO latind1 = 1,SIZE(uniquelatraw)
896  IF (uniquelatraw(latind1).GE.minlat) EXIT
897  END DO
898  DO latind2 = SIZE(uniquelatraw),1,-1
899  IF (uniquelatraw(latind2).LE.maxlat) EXIT
900  END DO
901  DO lonind1 = 1,SIZE(uniquelonraw)
902  IF (uniquelonraw(lonind1).GE.minlon) EXIT
903  END DO
904  DO lonind2 = SIZE(uniquelonraw),1,-1
905  IF (uniquelonraw(lonind2).LE.maxlon) EXIT
906  END DO
907  WRITE(20,*) 'latind1, latind2, lonind1, lonind2 =', &
908  latind1, latind2, lonind1, lonind2
909  IF ((latind1.GE.latind2).OR.(lonind1.GE.lonind2)) THEN
910  WRITE(20,1400)
911  WRITE(6,1400)
912  stop 1
913  END IF
914  NULLIFY(uniquelat)
915  NULLIFY(uniquelon)
916  ALLOCATE(uniquelat(latind2-latind1+1))
917  ALLOCATE(uniquelon(lonind2-lonind1+1))
918  uniquelat = uniquelatraw(latind1:latind2)
919  uniquelon = uniquelonraw(lonind1:lonind2)
920  WRITE(20,*) 'In waveTracking_NWS_V2: Longitude range =', &
921  uniquelon(1), uniquelon(SIZE(uniquelon))
922  WRITE(20,*) ' Latitude range =', &
923  uniquelat(1), uniquelat(SIZE(uniquelat))
924 
925  ! Map is transposed (rotated by 90 deg), so that:
926  ! I (matrix row) represents Longitute
927  ! J (matrix column) represents Latitude
928  ! i.e. from this point onwards the indices (i,j) represents Cart. coordinates
929  ALLOCATE( mlon(SIZE(uniquelon),SIZE(uniquelat)) )
930  ALLOCATE( mlat(SIZE(uniquelon),SIZE(uniquelat)) )
931  !
932  maxi = SIZE(uniquelon)
933  maxj = SIZE(uniquelat)
934  DO i = 1,maxi
935  DO j = 1,maxj
936  mlon(i,j) = uniquelon(i)
937  mlat(i,j) = uniquelat(j)
938  END DO
939  END DO
940 #ifdef W3_MPI
941  END IF
942 #endif
943 
944 #ifdef W3_MPI
945  CALL mpi_bcast(maxi,1,mpi_integer,0,mpi_comm_world,ierr)
946  CALL mpi_bcast(maxj,1,mpi_integer,0,mpi_comm_world,ierr)
947  CALL mpi_bcast(maxts,1,mpi_integer,0,mpi_comm_world,ierr)
948 #endif
949 
950  ! Allocate the wsdat structure
951 #ifdef W3_MPI
952  IF (rank.EQ.0) THEN
953 #endif
954  WRITE(20,*) 'Allocating wsdat...'
955 #ifdef W3_MPI
956  END IF
957 #endif
958  NULLIFY(wsdat)
959  ALLOCATE(wsdat(maxts))
960 #ifdef W3_MPI
961  IF (rank.EQ.0) THEN
962 #endif
963  WRITE(20,*) 'SIZE(wsdat) = ',SIZE(wsdat)
964 #ifdef W3_MPI
965  END IF
966 #endif
967 
968  ! Allocate and initialize the wsdat array
969 #ifdef W3_MPI
970  IF (rank.EQ.0) THEN
971 #endif
972  DO tsa = 1,maxts
973  ALLOCATE(wsdat(tsa)%lat(maxi,maxj))
974  ALLOCATE(wsdat(tsa)%lon(maxi,maxj))
975  ALLOCATE(wsdat(tsa)%par(maxi,maxj))
976  ALLOCATE(wsdat(tsa)%wnd(maxi,maxj))
977 
978  DO j = 1,maxj
979  DO i = 1,maxi
980  wsdat(tsa)%lat(i,j)=mlat(i,j)
981  wsdat(tsa)%lon(i,j)=mlon(i,j)
982  wsdat(tsa)%maxi=maxi
983  wsdat(tsa)%maxj=maxj
984  wsdat(tsa)%par(i,j)%hs(1:10)=9999.
985  wsdat(tsa)%par(i,j)%tp(1:10)=9999.
986  wsdat(tsa)%par(i,j)%dir(1:10)=9999.
987  wsdat(tsa)%par(i,j)%dspr(1:10)=9999.
988  ! wsdat(tsA)%par(i,j)%wf(1:10)=9999.
989  wsdat(tsa)%par(i,j)%ipart(1:10)=0
990  wsdat(tsa)%par(i,j)%sys(1:10)=9999 ! 40.PAR Increase this array, or make allocatable
991  wsdat(tsa)%par(i,j)%ngbrSys(1:50)=9999
992  wsdat(tsa)%wnd(i,j)%wdir=9999.
993  wsdat(tsa)%wnd(i,j)%wspd=9999.
994  wsdat(tsa)%par(i,j)%checked=-1
995  END DO
996  END DO
997  END DO
998 
999  ! Assign to each line in partition file an entry in wsdat
1000  ! At each time step each point contains all numpart partitions.
1001  ! Only store the first 10 partitions.
1002  l = 1
1003 
1004  DO WHILE (l.LE.line)
1005  DO j = 1,maxj
1006  DO i = 1,maxi
1009  IF ( (abs(llat(l)-mlat(i,j)).LT.1.e-2).AND. &
1010  (abs(llon(l)-mlon(i,j)).LT.1.e-2) ) THEN
1011  ! WRITE(20,*) 'MATCHED! ',l,&
1012  ! llat(l),mlat(i,j),ABS(llat(l)-mlat(i,j)),&
1013  ! llon(l),mlon(i,j),ABS(llon(l)-mlon(i,j))
1014  wsdat(ts(l))%lat(i,j) = llat(l)
1015  wsdat(ts(l))%lon(i,j) = llon(l)
1016  ! --- Find ALL partition values associated with
1017  ! lat(i,j) and lon(i,j). Keep list index l
1018  ! fixed and recycle iline as variable index. ---
1019  iline = l
1020  k = 1
1021  DO WHILE ( &
1022  abs(wsdat(ts(l))%lat(i,j)-llat(iline)).LT.1.e-3 &
1023  .AND.abs(wsdat(ts(l))%lon(i,j)-llon(iline)).LT.1.e-3 )
1024  IF (k.LE.10) THEN
1025  wsdat(ts(iline))%par(i,j)%ipart(k) = k
1026  wsdat(ts(iline))%par(i,j)%hs(k) = hs0(iline)
1027  wsdat(ts(iline))%par(i,j)%tp(k) = tp0(iline)
1028  wsdat(ts(iline))%par(i,j)%dir(k) = dir0(iline)
1029  wsdat(ts(iline))%par(i,j)%dspr(k) = dspr0(iline)
1030  ! wsdat(ts(k))%par(i,j)%wf(k) = wf0(l)
1031  IF (k.EQ.1) THEN
1032  wsdat(ts(iline))%date = date0(iline)
1033  wsdat(ts(iline))%wnd(i,j)%wdir = wnddir0(iline)
1034  wsdat(ts(iline))%wnd(i,j)%wspd = wndspd0(iline)
1035  wsdat(ts(iline))%par(i,j)%checked = 0
1036  END IF
1037  END IF
1038  k = k + 1
1039  iline = iline + 1
1040  if (iline.GT.line) EXIT
1041  END DO
1042  ! --- Account for increment at the end of loop (400 CONTINUE)
1043  ! and go one element back in list because of increment. ---
1044  l = iline-1
1045  GOTO 400
1046  END IF
1047  END DO
1048  END DO
1049 400 CONTINUE
1050  IF (l+1.le.line) THEN
1051  IF (ts(l).LT.ts(l+1)) THEN
1052  k = line-l
1053  ! --- With each time step completed, deallocate processed 1:l
1054  ! elements from 1d array. Create a temporary array size of
1055  ! (l+1:line) with k elements and reallocate original array. ---
1056  IF (ALLOCATED(tmp_i4)) DEALLOCATE(tmp_i4)
1057  ! --- REALLOCATE(integer arrays) ---
1058  ALLOCATE(tmp_i4(k))
1059  tmp_i4(1:k) = ts((l+1):line)
1060  DEALLOCATE(ts)
1061  ALLOCATE(ts(k))
1062  ts(1:k) = tmp_i4(1:k)
1063  DEALLOCATE(tmp_i4)
1064  ! --- REALLOCATE(double precision arrays) ---
1065  IF (ALLOCATED(tmp_r8)) DEALLOCATE(tmp_r8)
1066  ALLOCATE(tmp_r8(k))
1067  tmp_r8(1:k) = date0((l+1):line)
1068  DEALLOCATE(date0)
1069  ALLOCATE(date0(k))
1070  date0(1:k) = tmp_r8(1:k)
1071  DEALLOCATE(tmp_r8)
1072  ! --- REALLOCATE(single precision arrays) ---
1073  IF (ALLOCATED(tmp_r4)) DEALLOCATE(tmp_r4)
1074  ALLOCATE(tmp_r4(k))
1075  tmp_r4(1:k) = llat((l+1):line)
1076  DEALLOCATE(llat)
1077  ALLOCATE(llat(k))
1078  llat(1:k) = tmp_r4(1:k)
1079  tmp_r4(1:k) = llon((l+1):line)
1080  DEALLOCATE(llon)
1081  ALLOCATE(llon(k))
1082  llon(1:k) = tmp_r4(1:k)
1083  tmp_r4(1:k) = hs0((l+1):line)
1084  DEALLOCATE(hs0)
1085  ALLOCATE(hs0(k))
1086  hs0(1:k) = tmp_r4(1:k)
1087  tmp_r4(1:k) = tp0((l+1):line)
1088  DEALLOCATE(tp0)
1089  ALLOCATE(tp0(k))
1090  tp0(1:k) = tmp_r4(1:k)
1091  tmp_r4(1:k) = dir0((l+1):line)
1092  DEALLOCATE(dir0)
1093  ALLOCATE(dir0(k))
1094  dir0(1:k) = tmp_r4(1:k)
1095  tmp_r4(1:k) = dspr0((l+1):line)
1096  DEALLOCATE(dspr0)
1097  ALLOCATE(dspr0(k))
1098  dspr0(1:k) = tmp_r4(1:k)
1099  tmp_r4(1:k) = wndspd0((l+1):line)
1100  DEALLOCATE(wndspd0)
1101  ALLOCATE(wndspd0(k))
1102  wndspd0(1:k) = tmp_r4(1:k)
1103  tmp_r4(1:k) = wnddir0((l+1):line)
1104  DEALLOCATE(wnddir0)
1105  ALLOCATE(wnddir0(k))
1106  wnddir0(1:k) = tmp_r4(1:k)
1107  DEALLOCATE(tmp_r4)
1108  line = k
1109  l = 0
1110  END IF
1111  END IF
1112  l = l + 1
1113  END DO
1114  !
1115  IF (ALLOCATED(ts)) DEALLOCATE(ts)
1116  IF (ALLOCATED(llat)) DEALLOCATE(llat)
1117  IF (ALLOCATED(llon)) DEALLOCATE(llon)
1118  IF (ALLOCATED(mlat)) DEALLOCATE(mlat)
1119  IF (ALLOCATED(mlon)) DEALLOCATE(mlon)
1120  IF (ALLOCATED(date0)) DEALLOCATE(date0)
1121  IF (ALLOCATED(hs0)) DEALLOCATE(hs0)
1122  IF (ALLOCATED(tp0)) DEALLOCATE(tp0)
1123  IF (ALLOCATED(dir0)) DEALLOCATE(dir0)
1124  IF (ALLOCATED(dspr0)) DEALLOCATE(dspr0)
1125  ! IF (ALLOCATED(wf0)) DEALLOCATE(wf0)
1126  IF (ALLOCATED(wndspd0)) DEALLOCATE(wndspd0)
1127  IF (ALLOCATED(wnddir0)) DEALLOCATE(wnddir0)
1128 #ifdef W3_MPI
1129  END IF
1130 #endif
1131 
1132 #ifdef W3_MPI
1133  ! Communicate the wsdat entries from rank=0 to other ranks
1134  DO tsa = t0,maxts
1135  irank = mod((tsa-t0),min(nproc,maxts))
1136  ! WRITE(20,*) 'Rank,irank=',rank,irank
1137  IF (irank.NE.0) THEN
1138  ! WRITE(20,*) 'Communicating for Rank,irank=',rank,irank
1139 
1140  IF (rank.EQ.irank) THEN
1141  ALLOCATE(wsdat(tsa)%lat(maxi,maxj))
1142  ALLOCATE(wsdat(tsa)%lon(maxi,maxj))
1143  ALLOCATE(wsdat(tsa)%par(maxi,maxj))
1144  ALLOCATE(wsdat(tsa)%wnd(maxi,maxj))
1145 
1146  DO j = 1,maxj
1147  DO i = 1,maxi
1148  wsdat(tsa)%maxi=maxi
1149  wsdat(tsa)%maxj=maxj
1150  wsdat(tsa)%par(i,j)%hs(1:10)=9999.
1151  wsdat(tsa)%par(i,j)%tp(1:10)=9999.
1152  wsdat(tsa)%par(i,j)%dir(1:10)=9999.
1153  wsdat(tsa)%par(i,j)%dspr(1:10)=9999.
1154  wsdat(tsa)%par(i,j)%ipart(1:10)=0
1155  wsdat(tsa)%par(i,j)%sys(1:10)=9999 ! 40.PAR Increase this array, or make allocatable
1156  wsdat(tsa)%par(i,j)%ngbrSys(1:50)=9999
1157  wsdat(tsa)%wnd(i,j)%wdir=9999.
1158  wsdat(tsa)%wnd(i,j)%wspd=9999.
1159  wsdat(tsa)%par(i,j)%checked=-1
1160  END DO
1161  END DO
1162  END IF
1163 
1164  DO j = 1,maxj
1165  DO i = 1,maxi
1166  tag1 = ((j-1)*maxi+i)*10
1167 
1168  IF (rank.EQ.0) THEN
1169  ! WRITE(6,*) '>> Sending: rank,irank,tag1=', &
1170  ! rank,irank,(tag1+1)
1171  commarr1 = (/wsdat(tsa)%par(i,j)%hs(:), &
1172  wsdat(tsa)%par(i,j)%tp(:), &
1173  wsdat(tsa)%par(i,j)%dir(:), &
1174  wsdat(tsa)%par(i,j)%dspr(:), &
1175  wsdat(tsa)%wnd(i,j)%wdir, &
1176  wsdat(tsa)%wnd(i,j)%wspd, &
1177  wsdat(tsa)%lat(i,j), &
1178  wsdat(tsa)%lon(i,j)/)
1179  CALL mpi_send(commarr1,44,mpi_real,irank, &
1180  (tag1+1),mpi_comm_world,ierr)
1181  END IF
1182  IF (rank.EQ.irank) THEN
1183  ! WRITE(6,*) '<< Receiving: rank,irank,tag1=', &
1184  ! rank,irank,(tag1+1)
1185  CALL mpi_recv(commarr1,44,mpi_real,0,(tag1+1), &
1186  mpi_comm_world,mpi_status,ierr)
1187  wsdat(tsa)%par(i,j)%hs = commarr1(1:10)
1188  wsdat(tsa)%par(i,j)%tp = commarr1(11:20)
1189  wsdat(tsa)%par(i,j)%dir = commarr1(21:30)
1190  wsdat(tsa)%par(i,j)%dspr = commarr1(31:40)
1191  wsdat(tsa)%wnd(i,j)%wdir = commarr1(41)
1192  wsdat(tsa)%wnd(i,j)%wspd = commarr1(42)
1193  wsdat(tsa)%lat(i,j) = commarr1(43)
1194  wsdat(tsa)%lon(i,j) = commarr1(44)
1195  END IF
1196 
1197  IF (rank.EQ.0) THEN
1198  CALL mpi_send(wsdat(tsa)%date,1, &
1199  mpi_double_precision,irank, &
1200  (tag1+2),mpi_comm_world,ierr)
1201  END IF
1202  IF (rank.EQ.irank) THEN
1203  CALL mpi_recv(wsdat(tsa)%date,1, &
1204  mpi_double_precision,0,(tag1+2), &
1205  mpi_comm_world,mpi_status,ierr)
1206  END IF
1207 
1208  IF (rank.EQ.0) THEN
1209  ! WRITE(6,*) '>> Sending: rank,irank,tag1=', &
1210  ! rank,irank,(tag1+3)
1211  commarr2 = (/wsdat(tsa)%par(i,j)%ipart(:), &
1212  wsdat(tsa)%par(i,j)%checked/)
1213  CALL mpi_send(commarr2,11, &
1214  mpi_integer,irank,(tag1+3),mpi_comm_world,ierr)
1215  END IF
1216  IF (rank.EQ.irank) THEN
1217  ! WRITE(6,*) '<< Receiving: rank,irank,tag1=', &
1218  ! rank,irank,(tag1+3)
1219  CALL mpi_recv(commarr2,11, &
1220  mpi_integer,0,(tag1+3), &
1221  mpi_comm_world,mpi_status,ierr)
1222  wsdat(tsa)%par(i,j)%ipart(:) = commarr2(1:10)
1223  wsdat(tsa)%par(i,j)%checked = commarr2(11)
1224  END IF
1225 
1226  END DO
1227  END DO
1228  END IF
1229  END DO
1230 
1231  CALL mpi_barrier(mpi_comm_world,ierr)
1232 #endif
1233 
1234 
1235 #ifdef W3_MPI
1236  IF (rank.EQ.0) THEN
1237 #endif
1238  ! ----*** Test Output *** --------------------------------------------------
1239  IF (testout) THEN
1240  !-----RAW PARTITION output: Coordinates
1241  OPEN(unit=31,file='PART_COORD.OUT',status='unknown')
1242 
1243  WRITE(31,*) 'Longitude ='
1244  DO j = maxj,1,-1
1245  DO i = 1,maxi
1246  WRITE(31,'(F7.2)',advance='NO') wsdat(1)%lon(i,j)
1247  END DO
1248  WRITE(31,'(A)',advance='YES') ''
1249  END DO
1250 
1251  WRITE(31,*) 'Latitude = '
1252  DO j = maxj,1,-1
1253  DO i = 1,maxi
1254  WRITE(31,'(F7.2)',advance='NO') wsdat(1)%lat(i,j)
1255  END DO
1256  WRITE(31,'(A)',advance='YES') ''
1257  END DO
1258 
1259  CLOSE(31)
1260 
1261  !-----RAW PARTITION output: hs
1262  OPEN(unit=32, file='PART_HSIGN.OUT', &
1263  status='unknown')
1264 
1265  maxpartout = 5
1266  DO tsa = 1,SIZE(wsdat)
1267  WRITE(32,'(I4,71x,A)') tsa,'Time step'
1268  WRITE(32,'(I4,71x,A)') maxpartout,'Tot number of raw partitions'
1269  DO k = 1,maxpartout
1270  WRITE(32,'(I4,71x,A)') k,'System number'
1271  WRITE(32,'(I4,71x,A)') 9999,'Number of points in system'
1272  DO j = maxj,1,-1
1273  DO i = 1,maxi
1274  WRITE(32,'(F8.2)',advance='NO') wsdat(tsa)%par(i,j)%hs(k)
1275  END DO
1276  WRITE(32,'(A)',advance='YES') ''
1277  END DO
1278  END DO
1279  END DO
1280 
1281  CLOSE(32)
1282 
1283  !-----RAW PARTITION output: tp
1284  ! OPEN(unit=33,recl=2147483646, file='PART_TP.OUT', &
1285  ! status='unknown')
1286  OPEN(unit=33, file='PART_TP.OUT', &
1287  status='unknown')
1288 
1289  DO tsa = 1,SIZE(wsdat)
1290  WRITE(33,'(I4,71x,A)') tsa,'Time step'
1291  WRITE(33,'(I4,71x,A)') maxpartout,'Tot number of raw partitions'
1292  DO k = 1,maxpartout
1293  WRITE(33,'(I4,71x,A)') k,'System number'
1294  WRITE(33,'(I4,71x,A)') 9999,'Number of points in system'
1295  DO j = maxj,1,-1
1296  DO i = 1,maxi
1297  WRITE(33,'(F8.2)',advance='NO') wsdat(tsa)%par(i,j)%tp(k)
1298  END DO
1299  WRITE(33,'(A)',advance='YES') ''
1300  END DO
1301  END DO
1302  END DO
1303 
1304  CLOSE(33)
1305 
1306  !-----RAW PARTITION output: dir
1307  OPEN(unit=34, file='PART_DIR.OUT', &
1308  status='unknown')
1309 
1310  DO tsa = 1,SIZE(wsdat)
1311  WRITE(34,'(I4,71x,A)') tsa,'Time step'
1312  WRITE(34,'(I4,71x,A)') maxpartout,'Tot number of raw partitions'
1313  DO k = 1,maxpartout
1314  WRITE(34,'(I4,71x,A)') k,'System number'
1315  WRITE(34,'(I4,71x,A)') 9999,'Number of points in system'
1316  DO j = maxj,1,-1
1317  DO i = 1,maxi
1318  WRITE(34,'(F8.2)',advance='NO') wsdat(tsa)%par(i,j)%dir(k)
1319  END DO
1320  WRITE(34,'(A)',advance='YES') ''
1321  END DO
1322  END DO
1323  END DO
1324 
1325  CLOSE(34)
1326 
1327  !-----RAW PARTITION output: dspr
1328  OPEN(unit=35, file='PART_DSPR.OUT', &
1329  status='unknown')
1330 
1331  DO tsa = 1,SIZE(wsdat)
1332  WRITE(35,'(I4,71x,A)') tsa,'Time step'
1333  WRITE(35,'(I4,71x,A)') maxpartout,'Tot number of raw partitions'
1334  DO k = 1,maxpartout
1335  WRITE(35,'(I4,71x,A)') k,'System number'
1336  WRITE(35,'(I4,71x,A)') 9999,'Number of points in system'
1337  DO j = maxj,1,-1
1338  DO i = 1,maxi
1339  WRITE(35,'(F8.2)',advance='NO') &
1340  wsdat(tsa)%par(i,j)%dspr(k)
1341  END DO
1342  WRITE(35,'(A)',advance='YES') ''
1343  END DO
1344  END DO
1345  END DO
1346 
1347  CLOSE(35)
1348  END IF
1349 #ifdef W3_MPI
1350  END IF
1351 #endif
1352 
1353  ! ------------------------------------------------------------------------
1354 
1355  ! Allocate the sysA structure
1356 #ifdef W3_MPI
1357  IF (rank.EQ.0) THEN
1358 #endif
1359  WRITE(20,*) 'Allocating sysA...'
1360 #ifdef W3_MPI
1361  END IF
1362 #endif
1363  ALLOCATE( sysa(maxts) )
1364 #ifdef W3_MPI
1365  IF (rank.EQ.0) THEN
1366 #endif
1367  WRITE(20,*) 'SIZE(sysA) = ',SIZE(sysa)
1368  WRITE(6,1020) ' Number of time levels being processed:',SIZE(sysa)
1369 1020 FORMAT(a,i4)
1370 #ifdef W3_MPI
1371  END IF
1372 #endif
1373 
1374  ! Allocate maxSys
1375  ALLOCATE( maxsys(maxts) )
1376  ELSE
1377  ! Raw partitioning data from wave model memory, via the array wsdat.
1378  ! Set maxTs to the time step to compute: 1=first time step, 2=otherwise
1379  maxts = tmax
1380  t0 = tcur
1381 
1382  ! Allocate the sysA structure
1383  ALLOCATE( sysa(1) ) !Change to sysA(2)?
1384  ! Allocate maxSys
1385  ALLOCATE( maxsys(1) ) !Change to maxSys(2)?
1386  END IF
1387 
1388  ! Big loop over all time levels
1389 #ifdef W3_MPI
1390  IF (rank.EQ.0) THEN
1391 #endif
1392  WRITE(6,*) 'Performing spatial tracking...'
1393 #ifdef W3_MPI
1394  END IF
1395  ! WRITE(20,*) 'rank,t0,maxTs,nproc =',rank,t0,maxTs,nproc
1396  DO tsa = (t0+rank),maxts,min(nproc,maxts)
1397  ! WRITE(20,*) 'Computing: Rank, tsA =',rank,tsA
1398 #endif
1399 #ifdef W3_SHRD
1400  DO tsa = t0,maxts
1401 #endif
1402 
1403  WRITE(20,*) 'Call spiralTrackV3, tsA=',tsa,'...'
1404  CALL spiraltrackv3 ( wsdat(tsa), dirknob, perknob, wetpts, &
1405  hsknob, seedlat, seedlon, &
1406  maxsys(tsa), sysa(tsa)%sys )
1407 
1408  WRITE(20,*) '*** SIZE(sysA(1:tsA)%sys) at end of time step', &
1409  tsa,':'
1410  WRITE(20,*) SIZE(sysa(tsa)%sys)
1411 #ifdef W3_SHRD
1412  END DO
1413 #endif
1414 #ifdef W3_MPI
1415  END DO
1416 #endif
1417 
1418 #ifdef W3_MPI
1419  CALL mpi_barrier(mpi_comm_world,ierr)
1420 
1421  !! Define communicator for array of integers in structure "system"
1422  ! DOMSIZE = maxI*maxJ
1423  ! WRITE(20,*) 'Rank',rank,'DOMSIZE =',DOMSIZE
1424  ! CALL MPI_TYPE_CONTIGUOUS(DOMSIZE,MPI_INTEGER,MPI_INT_DOMARR,IERR)
1425  ! CALL MPI_TYPE_COMMIT(MPI_INT_DOMARR,IERR)
1426  ! CALL MPI_TYPE_EXTENT(MPI_INT_DOMARR,EXTENT,IERR)
1427  ! WRITE(20,*) 'Rank',rank,'has set up communicator MPI_INT_DOMARR, &
1428  ! size =',EXTENT
1429 
1430  !! Define communicator for array of reals in structure "system"
1431  ! CALL MPI_TYPE_CONTIGUOUS(DOMSIZE,MPI_REAL,MPI_REAL_DOMARR,IERR)
1432  ! CALL MPI_TYPE_COMMIT(MPI_REAL_DOMARR,IERR)
1433  ! CALL MPI_TYPE_EXTENT(MPI_REAL_DOMARR,EXTENT,IERR)
1434  ! WRITE(20,*) 'Rank',rank,'has set up communicator MPI_REAL_DOMARR, &
1435  ! size =',EXTENT
1436 
1437  ! Communicate results back to rank 0
1438  DO tsa = t0,maxts
1439  irank = mod((tsa-t0),min(nproc,maxts))
1440  ! WRITE(20,*) 'Rank,irank=',rank,irank
1441  IF (irank.NE.0) THEN
1442  ! WRITE(20,*) 'Communicating for Rank,irank=',rank,irank
1443 
1444  ! Send maxSys(tsA) at each time level to rank 0
1445  tag1 = tsa
1446  IF (rank.EQ.irank) THEN
1447  ! Send results from current rank to rank 0 (blocking)
1448  ! WRITE(20,*) '>> Sending: rank,tsA,tag1=',rank,tsA,tag1
1449  CALL mpi_send(maxsys(tsa),1,mpi_integer,0,tag1, &
1450  mpi_comm_world,ierr)
1451  ! WRITE(20,*) 'Rank, IERR=',rank,IERR
1452  END IF
1453  IF (rank.EQ.0) THEN
1454  ! WRITE(20,*) '<< Receiving: rank,tsA,tag1=',rank,tsA,tag1
1455  CALL mpi_recv(maxsys(tsa),1,mpi_integer, &
1456  irank,tag1,mpi_comm_world,mpi_status,ierr)
1457  ! Allocate structure at this time level
1458  ALLOCATE( sysa(tsa)%sys(maxsys(tsa)) )
1459  DO ic = 1,maxsys(tsa)
1460  NULLIFY( sysa(tsa)%sys(ic)%i )
1461  NULLIFY( sysa(tsa)%sys(ic)%j )
1462  NULLIFY( sysa(tsa)%sys(ic)%lon )
1463  NULLIFY( sysa(tsa)%sys(ic)%lat )
1464  NULLIFY( sysa(tsa)%sys(ic)%hs )
1465  NULLIFY( sysa(tsa)%sys(ic)%tp )
1466  NULLIFY( sysa(tsa)%sys(ic)%dir)
1467  NULLIFY( sysa(tsa)%sys(ic)%dspr)
1468  ALLOCATE( sysa(tsa)%sys(ic)%i(maxi*maxj) )
1469  ALLOCATE( sysa(tsa)%sys(ic)%j(maxi*maxj) )
1470  ALLOCATE( sysa(tsa)%sys(ic)%lon(maxi*maxj) )
1471  ALLOCATE( sysa(tsa)%sys(ic)%lat(maxi*maxj) )
1472  ALLOCATE( sysa(tsa)%sys(ic)%hs(maxi*maxj) )
1473  ALLOCATE( sysa(tsa)%sys(ic)%tp(maxi*maxj) )
1474  ALLOCATE( sysa(tsa)%sys(ic)%dir(maxi*maxj) )
1475  ALLOCATE( sysa(tsa)%sys(ic)%dspr(maxi*maxj) )
1476  sysa(tsa)%sys(ic)%i(:) = 9999
1477  sysa(tsa)%sys(ic)%j(:) = 9999
1478  sysa(tsa)%sys(ic)%lon(:) = 9999.
1479  sysa(tsa)%sys(ic)%lat(:) = 9999.
1480  sysa(tsa)%sys(ic)%hs(:) = 9999.
1481  sysa(tsa)%sys(ic)%tp(:) = 9999.
1482  sysa(tsa)%sys(ic)%dir(:) = 9999.
1483  sysa(tsa)%sys(ic)%dspr(:) = 9999.
1484  sysa(tsa)%sys(ic)%hsMean = 9999.
1485  sysa(tsa)%sys(ic)%tpMean = 9999.
1486  sysa(tsa)%sys(ic)%dirMean = 9999.
1487  sysa(tsa)%sys(ic)%sysInd = 9999
1488  sysa(tsa)%sys(ic)%nPoints = 9999
1489  sysa(tsa)%sys(ic)%grp = 9999
1490  END DO
1491  END IF
1492 
1493  ! Send data fields at each (tsA,ic) combination
1494  IF ((rank.EQ.0).OR.(rank.EQ.irank)) THEN
1495  DO ic = 1, maxsys(tsa)
1496  ! Construct a unique tag for each message
1497  tag2 = tsa*10000 + ic*100
1498  domsize = maxi*maxj
1499 
1500  IF (rank.EQ.irank) THEN
1501  ! WRITE(20,*) '>> Sending: rank,irank,tag2=', &
1502  ! rank,irank,(tag2+1)
1503  CALL mpi_send(sysa(tsa)%sys(ic)%i(:),domsize, &
1504  mpi_integer,0,(tag2+1),mpi_comm_world,req(1),ierr)
1505  END IF
1506  IF (rank.EQ.0) THEN
1507  ! WRITE(20,*) '<< Receiving: rank,irank,tag2=', &
1508  ! rank,irank,(tag2+1)
1509  CALL mpi_recv(sysa(tsa)%sys(ic)%i(:),domsize, &
1510  mpi_integer,irank,(tag2+1), &
1511  mpi_comm_world,mpi_status,req(2),ierr)
1512  END IF
1513  ! CALL MPI_WAITALL(2,REQ,ISTAT,IERR)
1514 
1515  IF (rank.EQ.irank) THEN
1516  ! WRITE(20,*) '>> Sending: rank,irank,tag2=', &
1517  ! rank,irank,(tag2+2)
1518  CALL mpi_send(sysa(tsa)%sys(ic)%j(:),domsize, &
1519  mpi_integer,0,(tag2+2),mpi_comm_world,req(1),ierr)
1520  END IF
1521  IF (rank.EQ.0) THEN
1522  ! WRITE(20,*) '<< Receiving: rank,irank,tag2=', &
1523  ! rank,irank,(tag2+2)
1524  CALL mpi_recv(sysa(tsa)%sys(ic)%j(:),domsize, &
1525  mpi_integer,irank,(tag2+2), &
1526  mpi_comm_world,mpi_status,req(2),ierr)
1527  END IF
1528  ! CALL MPI_WAITALL(2,REQ,ISTAT,IERR)
1529 
1530  IF (rank.EQ.irank) THEN
1531  ! WRITE(20,*) '>> Sending: rank,tag2=',rank,(tag2+3)
1532  CALL mpi_send(sysa(tsa)%sys(ic)%lon(:),domsize, &
1533  mpi_real,0,(tag2+3),mpi_comm_world,req(1),ierr)
1534  END IF
1535  IF (rank.EQ.0) THEN
1536  ! WRITE(20,*) '<< Receiving: rank,tag2=',rank,(tag2+3)
1537  CALL mpi_recv(sysa(tsa)%sys(ic)%lon(:),domsize, &
1538  mpi_real,irank,(tag2+3), &
1539  mpi_comm_world,mpi_status,req(2),ierr)
1540  END IF
1541  ! CALL MPI_WAITALL(2,REQ,ISTAT,IERR)
1542 
1543  IF (rank.EQ.irank) THEN
1544  ! WRITE(20,*) '>> Sending: rank,tag2=',rank,(tag2+4)
1545  CALL mpi_send(sysa(tsa)%sys(ic)%lat(:),domsize, &
1546  mpi_real,0,(tag2+4),mpi_comm_world,req(1),ierr)
1547  END IF
1548  IF (rank.EQ.0) THEN
1549  ! WRITE(20,*) '<< Receiving: rank,tag2=',rank,(tag2+4)
1550  CALL mpi_recv(sysa(tsa)%sys(ic)%lat(:),domsize, &
1551  mpi_real,irank,(tag2+4), &
1552  mpi_comm_world,mpi_status,req(2),ierr)
1553  END IF
1554  ! CALL MPI_WAITALL(2,REQ,ISTAT,IERR)
1555 
1556  IF (rank.EQ.irank) THEN
1557  ! WRITE(20,*) '>> Sending: rank,tag2=',rank,(tag2+5)
1558  CALL mpi_send(sysa(tsa)%sys(ic)%hs(:),domsize, &
1559  mpi_real,0,(tag2+5),mpi_comm_world,req(1),ierr)
1560  END IF
1561  IF (rank.EQ.0) THEN
1562  ! WRITE(20,*) '<< Receiving: rank,tag2=',rank,(tag2+5)
1563  CALL mpi_recv(sysa(tsa)%sys(ic)%hs(:),domsize, &
1564  mpi_real,irank,(tag2+5), &
1565  mpi_comm_world,mpi_status,req(2),ierr)
1566  END IF
1567  ! CALL MPI_WAITALL(2,REQ,ISTAT,IERR)
1568 
1569  IF (rank.EQ.irank) THEN
1570  ! WRITE(20,*) '>> Sending: rank,tag2=',rank,(tag2+6)
1571  CALL mpi_send(sysa(tsa)%sys(ic)%tp(:),domsize, &
1572  mpi_real,0,(tag2+6),mpi_comm_world,req(1),ierr)
1573  END IF
1574  IF (rank.EQ.0) THEN
1575  ! WRITE(20,*) '<< Receiving: rank,tag2=',rank,(tag2+6)
1576  CALL mpi_recv(sysa(tsa)%sys(ic)%tp(:),domsize, &
1577  mpi_real,irank,(tag2+6), &
1578  mpi_comm_world,mpi_status,req(2),ierr)
1579  END IF
1580  ! CALL MPI_WAITALL(2,REQ,ISTAT,IERR)
1581 
1582  IF (rank.EQ.irank) THEN
1583  ! WRITE(20,*) '>> Sending: rank,tag2=',rank,(tag2+7)
1584  CALL mpi_send(sysa(tsa)%sys(ic)%dir(:),domsize, &
1585  mpi_real,0,(tag2+7),mpi_comm_world,req(1),ierr)
1586  END IF
1587  IF (rank.EQ.0) THEN
1588  ! WRITE(20,*) '<< Receiving: rank,tag2=',rank,(tag2+7)
1589  CALL mpi_recv(sysa(tsa)%sys(ic)%dir(:),domsize, &
1590  mpi_real,irank,(tag2+7), &
1591  mpi_comm_world,mpi_status,req(2),ierr)
1592  END IF
1593  ! CALL MPI_WAITALL(2,REQ,ISTAT,IERR)
1594 
1595  IF (rank.EQ.irank) THEN
1596  ! WRITE(20,*) '>> Sending: rank,tag2=',rank,(tag2+8)
1597  CALL mpi_send(sysa(tsa)%sys(ic)%dspr(:),domsize, &
1598  mpi_real,0,(tag2+8),mpi_comm_world,req(1),ierr)
1599  END IF
1600  IF (rank.EQ.0) THEN
1601  ! WRITE(20,*) '<< Receiving: rank,tag2=',rank,(tag2+8)
1602  CALL mpi_recv(sysa(tsa)%sys(ic)%dspr(:),domsize, &
1603  mpi_real,irank,(tag2+8), &
1604  mpi_comm_world,mpi_status,req(2),ierr)
1605  END IF
1606  ! CALL MPI_WAITALL(2,REQ,ISTAT,IERR)
1607 
1608  IF (rank.EQ.irank) THEN
1609  ! WRITE(20,*) '>> Sending: rank,irank,tag2=', &
1610  ! rank,irank,(tag2+9)
1611  CALL mpi_send(sysa(tsa)%sys(ic)%hsMean,1,mpi_real, &
1612  0,(tag2+9),mpi_comm_world,ierr)
1613  END IF
1614  IF (rank.EQ.0) THEN
1615  ! WRITE(20,*) '<< Receiving: rank,irank,tag2=', &
1616  ! rank,irank,(tag2+9)
1617  CALL mpi_recv(sysa(tsa)%sys(ic)%hsMean,1,mpi_real, &
1618  irank,(tag2+9),mpi_comm_world,mpi_status,ierr)
1619  END IF
1620 
1621  IF (rank.EQ.irank) THEN
1622  ! WRITE(20,*) '>> Sending: rank,irank,tag2=', &
1623  ! rank,irank,(tag2+10)
1624  CALL mpi_send(sysa(tsa)%sys(ic)%tpMean,1,mpi_real, &
1625  0,(tag2+10),mpi_comm_world,ierr)
1626  END IF
1627  IF (rank.EQ.0) THEN
1628  ! WRITE(20,*) '<< Receiving: rank,irank,tag2=', &
1629  ! rank,irank,(tag2+10)
1630  CALL mpi_recv(sysa(tsa)%sys(ic)%tpMean,1,mpi_real, &
1631  irank,(tag2+10),mpi_comm_world,mpi_status,ierr)
1632  END IF
1633 
1634  IF (rank.EQ.irank) THEN
1635  ! WRITE(20,*) '>> Sending: rank,irank,tag2=', &
1636  ! rank,irank,(tag2+11)
1637  CALL mpi_send(sysa(tsa)%sys(ic)%dirMean,1,mpi_real, &
1638  0,(tag2+11),mpi_comm_world,ierr)
1639  END IF
1640  IF (rank.EQ.0) THEN
1641  ! WRITE(20,*) '<< Receiving: rank,irank,tag2=', &
1642  ! rank,irank,(tag2+11)
1643  CALL mpi_recv(sysa(tsa)%sys(ic)%dirMean,1,mpi_real, &
1644  irank,(tag2+11),mpi_comm_world,mpi_status,ierr)
1645  END IF
1646 
1647  IF (rank.EQ.irank) THEN
1648  ! WRITE(20,*) '>> Sending: rank,irank,tag2=', &
1649  ! rank,irank,(tag2+12)
1650  CALL mpi_send(sysa(tsa)%sys(ic)%sysInd,1,mpi_integer,&
1651  0,(tag2+12),mpi_comm_world,ierr)
1652  END IF
1653  IF (rank.EQ.0) THEN
1654  ! WRITE(20,*) '<< Receiving: rank,irank,tag2=', &
1655  ! rank,irank,(tag2+12)
1656  CALL mpi_recv(sysa(tsa)%sys(ic)%sysInd,1,mpi_integer,&
1657  irank,(tag2+12),mpi_comm_world,mpi_status,ierr)
1658  END IF
1659 
1660  IF (rank.EQ.irank) THEN
1661  ! WRITE(20,*) '>> Sending: rank,irank,tag2=', &
1662  ! rank,irank,(tag2+13)
1663  CALL mpi_send(sysa(tsa)%sys(ic)%nPoints,1,mpi_integer,&
1664  0,(tag2+13),mpi_comm_world,ierr)
1665  END IF
1666  IF (rank.EQ.0) THEN
1667  ! WRITE(20,*) '<< Receiving: rank,irank,tag2=', &
1668  ! rank,irank,(tag2+13)
1669  CALL mpi_recv(sysa(tsa)%sys(ic)%nPoints,1,mpi_integer,&
1670  irank,(tag2+13),mpi_comm_world,mpi_status,ierr)
1671  END IF
1672 
1673  IF (rank.EQ.irank) THEN
1674  ! WRITE(20,*) '>> Sending: rank,irank,tag2=', &
1675  ! rank,irank,(tag2+14)
1676  CALL mpi_send(sysa(tsa)%sys(ic)%grp,1,mpi_integer,&
1677  0,(tag2+14),mpi_comm_world,ierr)
1678  END IF
1679  IF (rank.EQ.0) THEN
1680  ! WRITE(20,*) '<< Receiving: rank,irank,tag2=', &
1681  ! rank,irank,(tag2+14)
1682  CALL mpi_recv(sysa(tsa)%sys(ic)%grp,1,mpi_integer,&
1683  irank,(tag2+14),mpi_comm_world,mpi_status,ierr)
1684  END IF
1685  END DO
1686  END IF
1687  END IF
1688  END DO
1689 
1690  CALL mpi_barrier(mpi_comm_world,ierr)
1691 
1692  ! CALL MPI_TYPE_FREE(MPI_INT_DOMARR,IERR)
1693  ! CALL MPI_TYPE_FREE(MPI_REAL_DOMARR,IERR)
1694 
1695 #endif
1696 
1697 #ifdef W3_MPI
1698  IF (rank.EQ.0) THEN
1699 #endif
1700  WRITE(6,*) 'Performing temporal tracking...'
1701  WRITE(20,*) 'Calling timeTrackingV2...'
1702  lonext = wsdat(1)%lon(maxi,1)-wsdat(1)%lon(1,1)
1703  latext = wsdat(1)%lat(1,maxj)-wsdat(1)%lat(1,1)
1704 
1705  CALL timetrackingv2 (sysa, maxsys, tptimeknob, dirtimeknob, 1, &
1706  maxgroup, dt, lonext, latext, maxi, maxj)
1707  !
1708 #ifdef W3_MPI
1709  END IF
1710 #endif
1711  !
1712  RETURN
1713  !
1714 802 CONTINUE
1715  WRITE (6,990) ioerr
1716  stop 1
1717 
1718 990 FORMAT (/' *** WAVEWATCH III ERROR IN W3STRKMD : '/ &
1719  ' ERROR IN READING FROM PARTITION FILE'/ &
1720  ' IOSTAT =',i5/)
1721 1000 FORMAT (f9.0,f7.0,f8.3,f8.3,14x,i3,7x,f5.1,f6.1,f5.1,f6.1)
1722 1010 FORMAT (3x,f8.2,f8.2,8x,f9.2,f9.2)
1723 1200 FORMAT (/' *** WAVEWATCH III ERROR IN W3STRKMD : '/ &
1724  ' ERROR IN READING PARTITION FILE '/ &
1725  ' INCOMPATIBLE ENDIANESS'/ )
1726 1300 FORMAT (/' *** WAVEWATCH III ERROR IN W3STRKMD : '/ &
1727  ' ERROR IN READING PARTITION FILE '/ &
1728  ' EXPECTED IDSTR "WAVEWATCH III PARTITIONED DATA FILE"'/ )
1729 1400 FORMAT (/' *** WAVEWATCH III ERROR IN W3STRKMD : '/ &
1730  ' ERROR IN FINDING DOMAIN TO PROCESS - '/ &
1731  ' SPECIFIED LAT/LON LIMITS WITHIN DOMAIN '/ &
1732  ' OF RAW PARTITION FILE?'/ )
1733 2001 FORMAT (/' *** WAVEWATCH III ERROR IN W3SYSTRK : '/ &
1734  ' ERROR IN OPENING INPUT FILE'/ )
1735 2002 FORMAT (/' *** WAVEWATCH III ERROR IN W3SYSTRK : '/ &
1736  ' PREMATURE END OF INPUT FILE'/ )
1737 2003 FORMAT (/' *** WAVEWATCH III ERROR IN W3SYSTRK : '/ &
1738  ' PREMATURE END OF PARTITION FILE - '/ &
1739  ' TSTART=',f13.4/ )
1740  !
1741  !

References file(), constants::file_endian, include(), spiraltrackv3(), swapi4(), timetrackingv2(), and unique().

Referenced by ww3_systrk().

constants::pi
real, parameter pi
PI Value of Pi.
Definition: constants.F90:71
include
cmake src_list cmake include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_switches.cmake) check_switches("$
Definition: CMakeLists.txt:15
yowrankmodule::rank
type(t_rank), dimension(:), allocatable, public rank
Provides access to some information of all threads e.g.
Definition: yowrankModule.F90:68
scrip_timers::status
character(len=8), dimension(max_timers), save status
Definition: scrip_timers.f:63
file
file(STRINGS ${CMAKE_BINARY_DIR}/switch switch_strings) separate_arguments(switches UNIX_COMMAND $
Definition: CMakeLists.txt:3
w3snl4md::tsa
real, dimension(:,:), allocatable tsa
Definition: w3snl4md.F90:195