Description |
Finally, I figured out how to correct the shared-memory bug in the floats vertical random walk. I mentioned this problem before in src:ticket:472. Getting random number sequences in parallel is very tricky. It is very difficult to get identical ROMS solutions in serial and parallel when random numbers are involved, but it is possible.
- Changed the strategy of generating a normally-distributed random number sequence for random vertical walk velocity. A new global variable rwalk is created in mod_floats.F to store random number sequences for floats. This fixed the shared-memory bug when generating the random numbers.
- Changed the initialization handling of out-of-bounds floats. Previously, we have in inp_par.F:
FLT(ng)%Tinfo(ixgrd,nc)=MIN(MAX(0.5_r8,Fx0(i,ng)), &
& REAL(Lm(ng),r8)+0.5_r8)
FLT(ng)%Tinfo(iygrd,nc)=MIN(MAX(0.5_r8,Fy0(i,ng)), &
& REAL(Mm(ng),r8)+0.5_r8)
This limiting is eliminated in inp_par.F and grid_coords.F and now we have:
FLT(ng)%Tinfo(ixgrd,nc)=Fx0(i,ng)
FLT(ng)%Tinfo(iygrd,nc)=Fy0(i,ng)
- The checking for out-of-bounds initial locations is now done in step_floats.F when the floats are released:
IF ((Tinfo(ixgrd,l).lt.0.5_r8).or. &
& (Tinfo(iygrd,l).lt.0.5_r8).or. &
& (Tinfo(ixgrd,l).gt.REAL(Lm(ng),r8)+0.5_r8).or. &
& (Tinfo(iygrd,l).gt.REAL(Mm(ng),r8)+0.5_r8)) THEN
bounded(l)=.FALSE. ! outside application grid
END IF
This fixes a parallel bug when comparing trajectoris in serial and distributed-memory. Now the out-of-bounds floats in MPI solutions have the correct FillValue instead of a zero value.
- The random numbers are now computed with the parallel friendly routine gasdev.F. It uses the same efficient routines used to generate random numbers in the adjoint-based algorithms. The routine nrng.F (file utility.F) is eliminated.
- The random number sequence is only generated in the floats predictor step. This fixes the problem reported by Mark Hadfield in src:ticket:472. The 1/SQRT(2)=0.707 factor was due to the two independent random sequences (predictor and corrector steps). Many thanks to John Wilkin for bringing to our attention: if the variance of the random velocity on the predictor step is 1, and this is independent of the random velocity on the corrector step (also 1), then the two random step combined have a variance of only 1/2 with an standard deviation of 0.707.
|
Description |
Updated couple of routines associated with the floats:
- Changed routine gasdev.F which is used to compute normally-distributed random number sequences. This routine has several F90 constructs that maybe problematic in old compilers. This is obviously a compiler bug. If so, we get usually error in the following expression:
CALL array_copy (PACK(v1(ng:n), mask(ng:n)), v1(ng:), nn, m)
Some compilers either fail to recognize the vector array out of the intrinsic PACK function or its numerical representation even if the routine array_copy is inside of an interface. To avoid this problem, the above statement is replaced by:
mc=COUNT(mask(ng:n))
v3(1:mc)=PACK(v1(ng:n), mask(ng:n))
CALL array_copy (v3(1:mc), v1(ng:), nn, m)
Many thanks to first Julio Sheinbaum for reporting this one during the ROMS 4D-Var workshop and recently to Diego Narvaez when trying the floats.
- Corrected an out-of-range computation in grid_coords.F when computing the initial depths for out-of-bounds initial float locations. The following conditional is added:
IF (MyThread(l).and. &
& ((DRIFTER(ng)%Tinfo(ixgrd,l).ge.0.5_r8).and. &
& (DRIFTER(ng)%Tinfo(iygrd,l).ge.0.5_r8).and. &
& (DRIFTER(ng)%Tinfo(ixgrd,l).le. &
& REAL(Lm(ng),r8)+0.5_r8).and. &
& (DRIFTER(ng)%Tinfo(iygrd,l).le. &
& REAL(Mm(ng),r8)+0.5_r8))) THEN
...
|