--- MITgcm/pkg/generic_advdiff/gad_dst3fl_adv_x.F 2005/08/19 22:19:35 1.7 +++ MITgcm/pkg/generic_advdiff/gad_dst3fl_adv_x.F 2005/10/18 16:03:55 1.8 @@ -1,4 +1,4 @@ -C $Header: /home/ubuntu/mnt/e9_copy/MITgcm/pkg/generic_advdiff/gad_dst3fl_adv_x.F,v 1.7 2005/08/19 22:19:35 heimbach Exp $ +C $Header: /home/ubuntu/mnt/e9_copy/MITgcm/pkg/generic_advdiff/gad_dst3fl_adv_x.F,v 1.8 2005/10/18 16:03:55 jmc Exp $ C $Name: $ #include "GAD_OPTIONS.h" @@ -36,11 +36,17 @@ INTEGER i,j _RL Rjm,Rj,Rjp,cfl,d0,d1,psiP,psiM,thetaP,thetaM _RL uFld + _RL thetaMax + PARAMETER( thetaMax = 1.D+20 ) + +C- jmc: an alternative would be to compute directly psiM*Rj & psiP*Rj +C (if Rj*Rjm < 0 => psiP*Rj = 0 , elsef Rj > 0 ... , else ... ) +C with no need to compute thetaM (might be easier to differentiate) DO j=1-Oly,sNy+Oly - uT(1-Olx,j)=0.D0 - uT(2-Olx,j)=0.D0 - uT(sNx+Olx,j)=0.D0 + uT(1-Olx,j)=0. _d 0 + uT(2-Olx,j)=0. _d 0 + uT(sNx+Olx,j)=0. _d 0 DO i=1-Olx+2,sNx+Olx-1 Rjp=(tracer(i+1,j)-tracer( i ,j))*maskLocW(i+1,j) Rj =(tracer( i ,j)-tracer(i-1,j))*maskLocW( i ,j) @@ -50,20 +56,37 @@ uFld = uTrans(i,j)*recip_dyG(i,j,bi,bj) & *recip_drF(k)*recip_hFacW(i,j,k,bi,bj) cfl=abs(uFld*deltaTloc*recip_dxC(i,j,bi,bj)) - d0=(2.D0-cfl)*(1.D0-cfl)*oneSixth - d1=(1.D0-cfl*cfl)*oneSixth + d0=(2. _d 0 -cfl)*(1. _d 0 -cfl)*oneSixth + d1=(1. _d 0 -cfl*cfl)*oneSixth + +C- the old version: can produce overflow, division by zero, +c and is wrong for tracer with low concentration: +c thetaP=Rjm/(1.D-20+Rj) +c thetaM=Rjp/(1.D-20+Rj) +C- the right expression, but not bounded: c thetaP=0.D0 -c IF (Rj.NE.0.D0) thetaP=Rjm/Rj - thetaP=Rjm/(1.D-20+Rj) - psiP=d0+d1*thetaP - psiP=max(0.D0, min(min(1.D0,psiP), - & (1.D0-cfl)/(1.D-20+cfl)*thetaP)) - thetaM=Rjp/(1.D-20+Rj) c thetaM=0.D0 +c IF (Rj.NE.0.D0) thetaP=Rjm/Rj c IF (Rj.NE.0.D0) thetaM=Rjp/Rj +C- prevent |thetaP,M| to reach too big value: + IF ( ABS(Rj)*thetaMax .LE. ABS(Rjm) ) THEN + thetaP=SIGN(thetaMax,Rjm*Rj) + ELSE + thetaP=Rjm/Rj + ENDIF + IF ( ABS(Rj)*thetaMax .LE. ABS(Rjp) ) THEN + thetaM=SIGN(thetaMax,Rjp*Rj) + ELSE + thetaM=Rjp/Rj + ENDIF + + psiP=d0+d1*thetaP + psiP=MAX(0. _d 0, MIN(MIN(1. _d 0,psiP), + & thetaP*(1. _d 0 -cfl)/(cfl+1. _d -20) )) psiM=d0+d1*thetaM - psiM=max(0.D0, min(min(1.D0,psiM), - & (1.D0-cfl)/(1.D-20+cfl)*thetaM)) + psiM=MAX(0. _d 0, MIN(MIN(1. _d 0,psiM), + & thetaM*(1. _d 0 -cfl)/(cfl+1. _d -20) )) + uT(i,j)= & 0.5*(uTrans(i,j)+abs(uTrans(i,j))) & *( Tracer(i-1,j) + psiP*Rj )