tiny bugs? in metrics.F and nesting.F

Bug reports, work arounds and fixes

Moderators: arango, robertson

Post Reply
Message
Author
tac
Posts: 1
Joined: Mon Nov 18, 2013 10:35 pm
Location: Port and Airport Research Institute

tiny bugs? in metrics.F and nesting.F

#1 Post by tac » Fri Jan 18, 2019 7:50 am

Hi all,

I've been working on a storm surge simulation with two-way nesting,
and encountered errors if baloclinic timestep dt at child grid is less than 1.

For example, if parent timestep dt(dg) = 3 and child timestep dt(ig) = 0.6,
then ROMS reported the following error:

METRICS - illegal timestep size for finer reciever grid (rg),
It must be an exact divisible factor from donor grid (dg).


Therefore I checked ROMS/Utility/metrics.F and found that MOD function returned non-zero values in line 1081,
though the order was ~O(1E-11). So I modified slightly as following:

IF (MOD(dt(dg),dt(ig)).gt.1.0d-3) THEN

and the error disappeared.


However, there was the another issue in Nesting.F and it caused the error:

PUT_REFINE2D - unbounded contact points temporal: interpolation:
cr = 05 dg = 03 ng = 04
iic(dg) = 0000002 told = 2 tnew = 1
iic(ng) = 0000006 Wold = 1.00000 Wnew = -0.00000
time(ng) = ******* time(told) = ******* time(tnew) = *******
Found Error: 08 Line: 6237 Source: ROMS/Nonlinear/nesting.F
Found Error: 08 Line: 95 Source: ROMS/Utility/get_2dfld.F
Found Error: 08 Line: 134 Source: ROMS/Nonlinear/get_data.F
Found Error: 08 Line: 201 Source: ROMS/Nonlinear/main3d.F
Found Error: 08 Line: 298 Source: ROMS/Drivers/nl_ocean.h


The problem is that the weight value for time interpolation Wnew is negative.
So I added ABS function to Wold and Wnew in the subroutine put_refine2d and put_refine3d as following:

Wold=ABS(RollingTime(tnew,cr)-time(ng))
Wnew=ABS(time(ng)-RollingTime(told,cr))


So far, it seems that the correction works fine. :D

User avatar
arango
Site Admin
Posts: 1081
Joined: Wed Feb 26, 2003 4:41 pm
Location: IMCS, Rutgers University
Contact:

Re: tiny bugs? in metrics.F and nesting.F

#2 Post by arango » Tue Jan 22, 2019 7:24 pm

Thank you for reporting this problem. I forgot to take care of the roundoff issues with the interpolation weights when I implemented the single precision (SINGLE_PRECISION option) simulations.

Your suggested solutions are incorrect :!:

We cannot take the ABS value when computing the interpolation weights. It is really bad because the weights are exclusively between 0 and 1 for bounded linear interpolation. Otherwise, we have extrapolation which is not allowed in ROMS. The solution is to convert the time units from seconds to something smaller, say milliseconds. Then, we can have in nesting.F:

Code: Select all

!
!  Set linear time interpolation weights. Fractional seconds are
!  rounded to the nearest milliseconds integer towards zero in the
!  time interpolation weights.
!
      SecScale=1000.0_dp              ! seconds to milliseconds
!
      Wold=ANINT((RollingTime(tnew,cr)-time(ng))*SecScale,dp)
      Wnew=ANINT((time(ng)-RollingTime(told,cr))*SecScale,dp)
      fac=1.0_dp/(Wold+Wnew)
      Wold=fac*Wold
      Wnew=fac*Wnew
Notice that the scaling does not affect the values of Wold and Wnew. They still range between 0 and 1 since we multiple and divide the SecScale. One could scale to microseconds (SecSecale=1.0E+6_dp) but is not necessary.

Similarly, your fix in metrics.F is problematic since that conditional needs to exact to zero! The solution is to use the SecScale again:

Code: Select all

!
!  Check refined grid time-step.  The time-step size for refined grids
!  needs to be an exact mode multiple of its coarser donor grid.  In
!  principle, it can be a "RefineScale" factor smaller.  However, other
!  integer smaller or larger factor are allowed such that:
!
!    MOD(dt(dg)*SecScale, dt(rg)*SecScale) = 0   dg:  donor  coarse grid
!                                                rg:  receiver fine grid
!
!  Notice that SecScale is used to avoid roundoff when the timestep
!  between donor and receiver grids are small and less than one.
!
        SecScale=1000.0_dp              ! seconds to milliseconds
        DO ig=1,Ngrids
          IF (RefinedGrid(ig).and.(RefineScale(ig).gt.0)) THEN
            dg=CoarserDonor(ig)
            IF (MOD(dt(dg)*SecScale,dt(ig)*SecScale).ne.0.0_dp) THEN
              IF (DOMAIN(ng)%SouthWest_Test(tile)) THEN
                IF (Master) THEN
                  WRITE (stdout,100) ig, dt(ig), dg, dt(dg),            &
     &                               MOD(dt(dg),dt(ig))
I will update the code with these changes.

Post Reply