[MITgcm-support] Bug in external_fields_load when using periodicExternalForcing

Jean-Michel Campin jmc at ocean.mit.edu
Tue Apr 12 22:25:26 EDT 2011


Hi Christopher,

Thanks for your detailed bug report.
Going to fix this in a way similar to what you 
proposed (but without the "save" instruction, because
of TAF + not safe with multi-threading).

Cheers,
Jean-Michel

On Tue, Apr 12, 2011 at 12:47:03PM -0700, Christopher L. Wolfe wrote:
> Hi all,
>
> I appear to have found a bug in the part of external_fields_load which  
> calculates interpolation weights and which records to load when using  
> periodicExternalForcing. The bug arises due to round-off errors incurred  
> when the variables are converted to integers using INT and NINT. It can  
> cause the model to crash when it goes looking for "impossible" record  
> numbers and also result in the interpolation weights being calculated  
> incorrectly. As an example of what can go wrong, consider
>
> deltaTclock = 86400 (one day)
> externForcingCycle = 31536000 (one 365-day year)
> externForcingPeriod = 2628000 (1/12 of a 365-day year)
>
> For mod(myIter,365) = 10, 11, ..., 14 this gives intime0 = 13, which is  
> "impossible" given that there should be only 12 records. This causes the  
> model to crash since Iftm(n)-Ifprd*(intime0(n)-1) .eq. 0 when  
> mod(myIter,365) = 10, thus causing the model to go looking for record  
> number 13. Simply duplicating record 1 as record 13 will prevent the  
> crash, but now the interpolation weights will be calculated incorrectly.  
> In particular, for mod(myIter,365) = 10, 11, ..., 14 aWght < .5 when it  
> should be greater than 0.5.
>
> I've attached a diff which appears to fix these problems for the case  
> above, but I haven't extensively tested it with different values of  
> deltaTclock, externForcingCycle, etc. Also, I've introduced a SAVE  
> statement to make it easier to figure out whether a new record should be  
> loaded. This works in my case, but it will no doubt break TAF. It  
> shouldn't be hard to rewrite the routine to avoid the use of the SAVE  
> statement.
>
> Cheers,
> Christopher
>
> -----------------------------------------------------------
> Dr. Christopher L. Wolfe                  858-534-4560
> Climate, Atmospheric Science, and Physical Oceanography
> Scripps Institution of Oceanography, UCSD  clwolfe at ucsd.edu
> -----------------------------------------------------------
>
>
>
>

> --- export/home/cwolfe/docs/research/globe/global1x1_tot/code/external_fields_load.F	2011-04-12 12:14:03.000000000 -0700
> +++ home/cwolfe/data/output/MITgcm/model/src/external_fields_load.F	2010-03-29 13:05:49.000000000 -0700
> @@ -57,32 +57,40 @@
>  C     !LOCAL VARIABLES:
>  C     === Local arrays ===
>  C     aWght, bWght :: Interpolation weights
> -      INTEGER bi,bj,i,j,intime0,intime1,intimem1
> -      _RL aWght,bWght,rdt,mytm,ftm
> +      INTEGER bi,bj,i,j,intime0,intime1
> +      _RL aWght,bWght,rdt
>        _RL tmp1Wght, tmp2Wght
>        INTEGER nForcingPeriods,Imytm,Ifprd,Ifcyc,Iftm
> -      save intimem1
> -      data intimem1 /0/
>  CEOP
>  
>        IF ( periodicExternalForcing ) THEN
> +
> +C First call requires that we initialize everything to zero for safety
> +cph    has been shifted to ini_forcing.F
> +
>  C Now calculate whether it is time to update the forcing arrays
> -       nForcingPeriods = int(externForcingCycle/externForcingPeriod)
> -       mytm = myTime
> -     &        + externForcingCycle*(1-nint(myTime/externForcingCycle))
> -       ftm = mod(mytm+externForcingCycle-externForcingPeriod/2,
> -     &        externForcingCycle)
> +      rdt = 1. _d 0 / deltaTclock
> +      nForcingPeriods = NINT(externForcingCycle/externForcingPeriod)
> +      Imytm = NINT(myTime*rdt)
> +      Ifprd = NINT(externForcingPeriod*rdt)
> +      Ifcyc = NINT(externForcingCycle*rdt)
> +      Imytm = Imytm + Ifcyc*( 1 - NINT(myTime/externForcingCycle) )
> +      Iftm  = MOD( Imytm+Ifcyc-Ifprd/2, Ifcyc)
>       
> -       intime0 = 1 + int(ftm/externForcingPeriod)
> +      intime0 = 1 + INT(Iftm/Ifprd)
>         intime1 = 1 + mod(intime0,nForcingPeriods)
> -       
> -       tmp1Wght = ftm-externForcingPeriod*(intime0 - 1)
> -       aWght = tmp1Wght/externForcingPeriod
> +C-jmc: with some option of g77, FLOAT results in real*4 evaluation
> +C      of aWght; using DFLOAT always force real*8 computation:
> +c     aWght = DFLOAT( Iftm-Ifprd*(intime0 - 1) ) / DFLOAT( Ifprd )
> +C-ph: however, TAF doesnt recognize DFLOAT,
> +C-jmc: so let me try this:
> +      tmp1Wght = FLOAT( Iftm-Ifprd*(intime0 - 1) )
> +      tmp2Wght = FLOAT( Ifprd )
> +      aWght =  tmp1Wght / tmp2Wght
>         bWght = 1. _d 0 - aWght
>  
>        IF (
> -     &  intime0 .EQ. intimem1
> -     &  .OR. myTime .Eq. 0
> +     &  Iftm-Ifprd*(intime0-1) .EQ. 0
>       &  .OR. myIter .EQ. nIter0
>       & ) THEN
>  
> @@ -208,8 +216,6 @@
>  
>        ENDIF
>  
> -      intimem1 = intime1
> -      
>  C--   Interpolate fu,fv,Qnet,EmPmR,SST,SSS,Qsw
>        DO bj = myByLo(myThid), myByHi(myThid)
>         DO bi = myBxLo(myThid), myBxHi(myThid)

> _______________________________________________
> MITgcm-support mailing list
> MITgcm-support at mitgcm.org
> http://mitgcm.org/mailman/listinfo/mitgcm-support




More information about the MITgcm-support mailing list