2 |
C $Name$ |
C $Name$ |
3 |
|
|
4 |
#include "OPPS_OPTIONS.h" |
#include "OPPS_OPTIONS.h" |
5 |
|
#undef OPPS_ORGCODE |
6 |
|
|
7 |
|
C-- File opps_calc.F: |
8 |
|
C-- Contents |
9 |
|
C-- o OPPS_CALC |
10 |
|
C-- o STATE1 |
11 |
|
C-- o NLOPPS |
12 |
|
|
13 |
|
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
14 |
CBOP |
CBOP |
15 |
C !ROUTINE: OPPS_CALC |
C !ROUTINE: OPPS_CALC |
16 |
|
|
22 |
I I, J, bi, bj, myTime, myIter, myThid ) |
I I, J, bi, bj, myTime, myIter, myThid ) |
23 |
|
|
24 |
C !DESCRIPTION: \bv |
C !DESCRIPTION: \bv |
25 |
C /=====================================================================\ |
C *=====================================================================* |
26 |
C | SUBROUTINE OPPS_CALC | |
C | SUBROUTINE OPPS_CALC | |
27 |
C | o Compute all OPPS fields defined in OPPS.h | |
C | o Compute all OPPS fields defined in OPPS.h | |
28 |
C |=====================================================================| |
C *=====================================================================* |
29 |
C | This subroutine is based on the routine 3dconvection.F | |
C | This subroutine is based on the routine 3dconvection.F | |
30 |
C | by E. Skyllingstad (?) | |
C | by E. Skyllingstad (?) | |
31 |
C | plenty of modifications to make it work: | |
C | plenty of modifications to make it work: | |
61 |
C | o TODO: | |
C | o TODO: | |
62 |
C | clean up the logic of the vertical loops and get rid off the | |
C | clean up the logic of the vertical loops and get rid off the | |
63 |
C | GOTO statements | |
C | GOTO statements | |
64 |
C \=====================================================================/ |
C *=====================================================================* |
|
IMPLICIT NONE |
|
|
C |
|
|
C-------------------------------------------------------------------- |
|
|
|
|
65 |
C \ev |
C \ev |
66 |
|
|
67 |
|
IMPLICIT NONE |
68 |
|
|
69 |
C !USES: ============================================================ |
C !USES: ============================================================ |
70 |
#include "SIZE.h" |
#include "SIZE.h" |
71 |
#include "EEPARAMS.h" |
#include "EEPARAMS.h" |
72 |
#include "PARAMS.h" |
#include "PARAMS.h" |
73 |
#include "OPPS.h" |
#include "OPPS.h" |
|
#include "FFIELDS.h" |
|
74 |
#include "GRID.h" |
#include "GRID.h" |
75 |
|
|
|
EXTERNAL DIFFERENT_MULTIPLE |
|
|
LOGICAL DIFFERENT_MULTIPLE |
|
|
|
|
76 |
C !INPUT PARAMETERS: =================================================== |
C !INPUT PARAMETERS: =================================================== |
77 |
c Routine arguments |
C Routine arguments |
78 |
c bi, bj - array indices on which to apply calculations |
C bi, bj :: array indices on which to apply calculations |
79 |
c myTime - Current time in simulation |
C myTime :: Current time in simulation |
80 |
|
|
81 |
INTEGER I, J, bi, bj, KMax, nTracer, nTracerInUse |
INTEGER I, J, bi, bj, KMax, nTracer, nTracerInUse |
82 |
INTEGER myThid, myIter |
INTEGER myThid, myIter |
84 |
_RL tracerEnv(Nr,nTracer),wVel(Nr) |
_RL tracerEnv(Nr,nTracer),wVel(Nr) |
85 |
|
|
86 |
#ifdef ALLOW_OPPS |
#ifdef ALLOW_OPPS |
87 |
|
C !FUNCTIONS: ========================================================== |
88 |
|
c EXTERNAL DIFFERENT_MULTIPLE |
89 |
|
c LOGICAL DIFFERENT_MULTIPLE |
90 |
|
_RL STATE1 |
91 |
|
|
92 |
C !LOCAL VARIABLES: ==================================================== |
C !LOCAL VARIABLES: ==================================================== |
93 |
c Local constants |
C Local constants |
94 |
C imin, imax, jmin, jmax - array computation indices |
C msgBuf :: Informational/error message buffer |
|
C msgBuf - Informational/error message buffer |
|
95 |
CHARACTER*(MAX_LEN_MBUF) msgBuf |
CHARACTER*(MAX_LEN_MBUF) msgBuf |
96 |
INTEGER K, K2, K2m1, K2p1, ktr |
INTEGER K, K2, K2m1, K2p1, ktr |
97 |
INTEGER ntime,nn,kmx,ic |
INTEGER ntime,nn,kmx,ic |
99 |
|
|
100 |
_RL wsqr,oldflux,newflux,entrainrate |
_RL wsqr,oldflux,newflux,entrainrate |
101 |
_RL pmix |
_RL pmix |
102 |
_RL D1,D2,state1 |
_RL D1, D2 |
103 |
_RL dz1,dz2 |
_RL dz1,dz2 |
104 |
_RL radius,StartingFlux |
_RL radius,StartingFlux |
105 |
_RL dtts,dt |
_RL dtts,dt |
107 |
_RL Paa(Nr,nTracer) |
_RL Paa(Nr,nTracer) |
108 |
_RL wda(Nr), mda(Nr), pda(Nr,nTracer) |
_RL wda(Nr), mda(Nr), pda(Nr,nTracer) |
109 |
C |
C |
110 |
C Pd, Wd - tracers, vertical velocity in plume |
C Pd, Wd :: tracers, vertical velocity in plume |
111 |
C Md - plume mass flux (?) |
C Md :: plume mass flux (?) |
112 |
C Ad - fractional area covered by plume |
C Ad :: fractional area covered by plume |
113 |
C Dd - density in plume |
C Dd :: density in plume |
114 |
C De - density of environment |
C De :: density of environment |
115 |
C PlumeEntrainment - |
C PlumeEntrainment :: |
116 |
_RL Ad(Nr),Wd(Nr),Dd(Nr),Md(Nr) |
_RL Ad(Nr),Wd(Nr),Dd(Nr),Md(Nr) |
117 |
_RL De(Nr) |
_RL De(Nr) |
118 |
_RL PlumeEntrainment(Nr) |
_RL PlumeEntrainment(Nr) |
119 |
_RL Pd(Nr,nTracer) |
_RL Pd(Nr,nTracer) |
120 |
CEOP |
CEOP |
121 |
|
|
|
|
|
122 |
C-- Check to see if should convect now |
C-- Check to see if should convect now |
123 |
C IF ( DIFFERENT_MULTIPLE(cAdjFreq,myTime,deltaTClock) ) THEN |
C IF ( DIFFERENT_MULTIPLE(cAdjFreq,myTime,deltaTClock) ) THEN |
124 |
IF ( .true. ) THEN |
IF ( .true. ) THEN |
126 |
|
|
127 |
C Copy some arrays |
C Copy some arrays |
128 |
dtts = dTtracerLev(1) |
dtts = dTtracerLev(1) |
129 |
C |
|
130 |
C start k-loop |
C start k-loop |
|
C |
|
131 |
|
|
132 |
DO k=1,KMax-1 |
DO k=1,KMax-1 |
133 |
c |
|
134 |
c initialize the plume T,S,density, and w velocity |
C initialize the plume T,S,density, and w velocity |
135 |
c |
|
136 |
DO ktr=1,nTracerInUse |
DO ktr=1,nTracerInUse |
137 |
Pd(k,ktr) = tracerEnv(k,ktr) |
Pd(k,ktr) = tracerEnv(k,ktr) |
138 |
ENDDO |
ENDDO |
139 |
Dd(k)=state1(Pd(k,2),Pd(k,1),i,j,k,bi,bj,myThid) |
Dd(k)=STATE1(Pd(k,2),Pd(k,1),i,j,k,bi,bj,myThid) |
140 |
De(k)=Dd(k) |
De(k)=Dd(k) |
141 |
CML print *, 'ml-opps:', i,j,k,tracerEnv(k,2),tracerEnv(k,1), |
CML print *, 'ml-opps:', i,j,k,tracerEnv(k,2),tracerEnv(k,1), |
142 |
CML & Dd(k),Pd(k,1),Pd(k,2) |
CML & Dd(k),Pd(k,1),Pd(k,2) |
146 |
CML avoid division by zero |
CML avoid division by zero |
147 |
CML IF (Wd(K) .EQ. 0.D0) Wd(K) = 2.23e-16 |
CML IF (Wd(K) .EQ. 0.D0) Wd(K) = 2.23e-16 |
148 |
CML) |
CML) |
149 |
c |
|
150 |
c guess at initial top grid cell vertical velocity |
C guess at initial top grid cell vertical velocity |
151 |
c |
|
152 |
CML Wd(k) = 0.03 |
CML Wd(k) = 0.03 |
153 |
c |
|
154 |
c these estimates of initial plume velocity based on plume size and |
C these estimates of initial plume velocity based on plume size and |
155 |
c top grid cell water mass |
C top grid cell water mass |
156 |
c |
|
157 |
c Wd(k) = 0.5*drF(k)/(dtts*FRACTIONAL_AREA) |
c Wd(k) = 0.5*drF(k)/(dtts*FRACTIONAL_AREA) |
158 |
c Wd(k) = 0.5*drF(k)/dtts |
c Wd(k) = 0.5*drF(k)/dtts |
159 |
c |
|
160 |
wsqr=Wd(k)*Wd(k) |
wsqr=Wd(k)*Wd(k) |
161 |
PlumeEntrainment(k) = 0.0 |
PlumeEntrainment(k) = 0.0 |
162 |
c |
|
|
c |
|
|
c |
|
163 |
#ifdef ALLOW_OPPS_DEBUG |
#ifdef ALLOW_OPPS_DEBUG |
164 |
IF ( OPPSdebugLevel.GE.debLevB ) THEN |
IF ( OPPSdebugLevel.GE.debLevB ) THEN |
165 |
WRITE(msgBuf,'(A,I3)') |
WRITE(msgBuf,'(A,I3)') |
174 |
|
|
175 |
dz2=DrF(k) |
dz2=DrF(k) |
176 |
DO k2=k,KMax-1 |
DO k2=k,KMax-1 |
177 |
D1=state1( Pd(k2,2), Pd(k2,1),i,j,k2+1,bi,bj,myThid) |
D1=STATE1( Pd(k2,2), Pd(k2,1),i,j,k2+1,bi,bj,myThid) |
178 |
D2=state1( tracerEnv(k2+1,2), tracerEnv(k2+1,1), |
D2=STATE1( tracerEnv(k2+1,2), tracerEnv(k2+1,1), |
179 |
& i,j,k2+1,bi,bj,myThid) |
& i,j,k2+1,bi,bj,myThid) |
180 |
De(k2+1)=D2 |
De(k2+1)=D2 |
181 |
c |
|
182 |
c To start downward, parcel has to initially be heavier than environment |
C To start downward, parcel has to initially be heavier than environment |
183 |
c but after it has started moving, we continue plume until plume tke or |
C but after it has started moving, we continue plume until plume tke or |
184 |
c flux goes negative |
C flux goes negative |
185 |
c |
|
186 |
CML & _hFacC(i,j,k-1,bi,bj) |
CML & _hFacC(i,j,k-1,bi,bj) |
187 |
CML & *_hFacC(i,j,k,bi,bj) .GT. 0. |
CML & *_hFacC(i,j,k,bi,bj) .GT. 0. |
188 |
CML & .AND. |
CML & .AND. |
189 |
IF (D2-D1 .LT. STABILITY_THRESHOLD.or.k2.ne.k) THEN |
IF (D2-D1 .LT. STABILITY_THRESHOLD.or.k2.ne.k) THEN |
190 |
dz1=dz2 |
dz1=dz2 |
191 |
dz2=DrF(k2+1) |
dz2=DrF(k2+1) |
192 |
c |
|
193 |
C find mass flux according to eq.(3) from paper by vertical integration |
C find mass flux according to eq.(3) from paper by vertical integration |
194 |
c |
|
195 |
newflux=oldflux+e2*radius*Wd(k2)*Dd(k2)* |
newflux=oldflux+e2*radius*Wd(k2)*Dd(k2)* |
196 |
& .5*(dz1+dz2) |
& .5*(dz1+dz2) |
197 |
CML print *, 'ml-opps:', i,j,k,oldflux,newflux,e2,radius, |
CML print *, 'ml-opps:', i,j,k,oldflux,newflux,e2,radius, |
198 |
CML & Wd(k2),Dd(k2),Pd(k2,1),Pd(k2,2),dz1,dz2 |
CML & Wd(k2),Dd(k2),Pd(k2,1),Pd(k2,2),dz1,dz2 |
199 |
c |
|
200 |
PlumeEntrainment(k2+1) = newflux/StartingFlux |
PlumeEntrainment(k2+1) = newflux/StartingFlux |
201 |
c |
|
202 |
IF(newflux.LE.0.0) then |
IF(newflux.LE.0.0) then |
203 |
#ifdef ALLOW_OPPS_DEBUG |
#ifdef ALLOW_OPPS_DEBUG |
204 |
IF ( OPPSdebugLevel.GE.debLevA ) THEN |
IF ( OPPSdebugLevel.GE.debLevA ) THEN |
212 |
if(maxdepth.eq.k) goto 1000 |
if(maxdepth.eq.k) goto 1000 |
213 |
goto 1 |
goto 1 |
214 |
endif |
endif |
215 |
c |
|
216 |
c entrainment rate is basically a scaled mass flux dM/M |
C entrainment rate is basically a scaled mass flux dM/M |
217 |
c |
|
218 |
entrainrate = (newflux - oldflux)/newflux |
entrainrate = (newflux - oldflux)/newflux |
219 |
oldflux = newflux |
oldflux = newflux |
220 |
c |
|
221 |
c |
C mix var(s) are the average environmental values over the two grid levels |
222 |
c mix var(s) are the average environmental values over the two grid levels |
|
|
c |
|
223 |
DO ktr=1,nTracerInUse |
DO ktr=1,nTracerInUse |
224 |
pmix=(dz1*tracerEnv(k2,ktr)+dz2*tracerEnv(k2+1,ktr)) |
pmix=(dz1*tracerEnv(k2,ktr)+dz2*tracerEnv(k2+1,ktr)) |
225 |
& /(dz1+dz2) |
& /(dz1+dz2) |
226 |
Pd(k2+1,ktr)=Pd(k2,ktr) |
Pd(k2+1,ktr)=Pd(k2,ktr) |
227 |
& - entrainrate*(pmix - Pd(k2,ktr)) |
& - entrainrate*(pmix - Pd(k2,ktr)) |
228 |
ENDDO |
ENDDO |
229 |
c |
|
230 |
c compute the density at this level for the buoyancy term in the |
C compute the density at this level for the buoyancy term in the |
231 |
c vertical k.e. equation |
C vertical k.e. equation |
232 |
c |
|
233 |
Dd(k2+1)=state1(Pd(k2+1,2),Pd(k2+1,1),i,j,k2+1,bi,bj,myThid) |
Dd(k2+1)=STATE1(Pd(k2+1,2),Pd(k2+1,1),i,j,k2+1,bi,bj,myThid) |
234 |
c |
|
235 |
c next, solve for the vertical velocity k.e. using combined eq. (4) |
C next, solve for the vertical velocity k.e. using combined eq. (4) |
236 |
c and eq (5) from the paper |
C and eq (5) from the paper |
237 |
c |
|
238 |
#ifdef ALLOW_OPPS_DEBUG |
#ifdef ALLOW_OPPS_DEBUG |
239 |
IF ( OPPSdebugLevel.GE.debLevA ) THEN |
IF ( OPPSdebugLevel.GE.debLevA ) THEN |
240 |
WRITE(msgBuf,'(A,3E12.4,I3)') |
WRITE(msgBuf,'(A,3E12.4,I3)') |
247 |
wsqr = wsqr - wsqr*abs(entrainrate)+ gravity* |
wsqr = wsqr - wsqr*abs(entrainrate)+ gravity* |
248 |
& (dz1*(Dd(k2)-De(k2))/De(k2) |
& (dz1*(Dd(k2)-De(k2))/De(k2) |
249 |
& +dz2*(Dd(k2+1)-De(k2+1))/De(k2+1)) |
& +dz2*(Dd(k2+1)-De(k2+1))/De(k2+1)) |
250 |
c |
|
251 |
c if negative k.e. then plume has reached max depth, get out of loop |
C if negative k.e. then plume has reached max depth, get out of loop |
252 |
c |
|
253 |
IF(wsqr.LE.0.0)then |
IF(wsqr.LE.0.0)then |
254 |
maxdepth = k2 |
maxdepth = k2 |
255 |
#ifdef ALLOW_OPPS_DEBUG |
#ifdef ALLOW_OPPS_DEBUG |
274 |
goto 1 |
goto 1 |
275 |
endif |
endif |
276 |
Wd(k2+1)=sqrt(wsqr) |
Wd(k2+1)=sqrt(wsqr) |
277 |
C |
|
278 |
C compute a new radius based on the new mass flux at this grid level |
C compute a new radius based on the new mass flux at this grid level |
279 |
C from Eq. (4) |
C from Eq. (4) |
280 |
C |
|
281 |
radius=sqrt(newflux/(Wd(k2)*Dd(k2))) |
radius=sqrt(newflux/(Wd(k2)*Dd(k2))) |
282 |
ELSE |
ELSE |
283 |
maxdepth=k2 |
maxdepth=k2 |
285 |
GOTO 1 |
GOTO 1 |
286 |
ENDIF |
ENDIF |
287 |
ENDDO |
ENDDO |
288 |
c |
|
289 |
c plume has reached the bottom |
C plume has reached the bottom |
290 |
c |
|
291 |
MaxDepth=kMax |
MaxDepth=kMax |
292 |
c |
|
293 |
1 CONTINUE |
1 CONTINUE |
294 |
c |
|
295 |
Ad(k)=FRACTIONAL_AREA |
Ad(k)=FRACTIONAL_AREA |
296 |
IC=0 |
IC=0 |
297 |
c |
|
298 |
c start iteration on fractional area, not used in OGCM implementation |
C start iteration on fractional area, not used in OGCM implementation |
299 |
c |
|
|
c |
|
300 |
DO IC=1,Max_ABE_Iterations |
DO IC=1,Max_ABE_Iterations |
301 |
c |
|
302 |
c |
C next compute the mass flux beteen each grid box using the entrainment |
303 |
c next compute the mass flux beteen each grid box using the entrainment |
|
|
c |
|
304 |
Md(k)=Wd(k)*Ad(k) |
Md(k)=Wd(k)*Ad(k) |
305 |
c |
|
306 |
DO k2=k+1,maxDepth |
DO k2=k+1,maxDepth |
307 |
Md(k2)=Md(k)*PlumeEntrainment(k2) |
Md(k2)=Md(k)*PlumeEntrainment(k2) |
308 |
#ifdef ALLOW_OPPS_DEBUG |
#ifdef ALLOW_OPPS_DEBUG |
314 |
ENDIF |
ENDIF |
315 |
#endif /* ALLOW_OPPS_DEBUG */ |
#endif /* ALLOW_OPPS_DEBUG */ |
316 |
ENDDO |
ENDDO |
317 |
c |
|
318 |
c Now move on to calculate new temperature using flux from |
C Now move on to calculate new temperature using flux from |
319 |
c Td, Sd, Wd, ta, sa, and we. Values for these variables are at |
C Td, Sd, Wd, ta, sa, and we. Values for these variables are at |
320 |
c center of grid cell, use weighted average to get boundary values |
C center of grid cell, use weighted average to get boundary values |
321 |
c |
|
322 |
c use a timestep limited by the GCM model timestep and the maximum plume |
C use a timestep limited by the GCM model timestep and the maximum plume |
323 |
c velocity (CFL criteria) |
C velocity (CFL criteria) |
324 |
c |
|
325 |
c |
C calculate the weighted wd, td, and sd |
|
c calculate the weighted wd, td, and sd |
|
|
c |
|
326 |
dt = dtts |
dt = dtts |
327 |
do k2=k,maxDepth-1 |
do k2=k,maxDepth-1 |
328 |
IF ( Wd(K2) .NE. 0. _d 0 ) dt = min(dt,drF(k2)/Wd(k2)) |
IF ( Wd(K2) .NE. 0. _d 0 ) dt = min(dt,drF(k2)/Wd(k2)) |
329 |
c |
|
330 |
c time integration will be integer number of steps to get one |
C time integration will be integer number of steps to get one |
331 |
c gcm time step |
C gcm time step |
332 |
c |
|
333 |
ntime = nint(0.5*int(dtts/dt)) |
ntime = nint(0.5*int(dtts/dt)) |
334 |
if(ntime.eq.0) then |
if(ntime.eq.0) then |
335 |
ntime = 1 |
ntime = 1 |
336 |
endif |
endif |
337 |
c |
|
338 |
c make sure area weighted vertical velocities match; in other words |
C make sure area weighted vertical velocities match; in other words |
339 |
c make sure mass in equals mass out at the intersection of each grid |
C make sure mass in equals mass out at the intersection of each grid |
340 |
c cell. Eq. (20) |
C cell. Eq. (20) |
341 |
c |
|
342 |
mda(k2) = (md(k2)*drF(k2)+md(k2+1)*drF(k2+1))/ |
mda(k2) = (md(k2)*drF(k2)+md(k2+1)*drF(k2+1))/ |
343 |
* (drF(k2)+drF(k2+1)) |
* (drF(k2)+drF(k2+1)) |
344 |
c |
|
345 |
wda(k2) = (wd(k2)*drF(k2)+wd(k2+1)*drF(k2+1))/ |
wda(k2) = (wd(k2)*drF(k2)+wd(k2+1)*drF(k2+1))/ |
346 |
* (drF(k2)+drF(k2+1)) |
* (drF(k2)+drF(k2+1)) |
347 |
c |
|
348 |
DO ktr = 1, nTracerInUse |
DO ktr = 1, nTracerInUse |
349 |
Pda(k2,ktr) = Pd(k2,ktr) |
Pda(k2,ktr) = Pd(k2,ktr) |
350 |
Paa(k2,ktr) = tracerEnv(k2+1,ktr) |
Paa(k2,ktr) = tracerEnv(k2+1,ktr) |
351 |
ENDDO |
ENDDO |
352 |
c |
|
353 |
enddo |
enddo |
354 |
dt = min(dt,dtts) |
dt = min(dt,dtts) |
355 |
#ifdef ALLOW_OPPS_DEBUG |
#ifdef ALLOW_OPPS_DEBUG |
363 |
DO ktr=1,nTracerInUse |
DO ktr=1,nTracerInUse |
364 |
Pda(maxdepth,ktr) = Pd(maxdepth,ktr) |
Pda(maxdepth,ktr) = Pd(maxdepth,ktr) |
365 |
ENDDO |
ENDDO |
366 |
C |
|
367 |
kmx = maxdepth-1 |
kmx = maxdepth-1 |
368 |
do nn=1,ntime |
do nn=1,ntime |
369 |
C |
|
370 |
C top point |
C top point |
371 |
C |
|
372 |
DO ktr = 1,nTracerInUse |
DO ktr = 1,nTracerInUse |
373 |
tracerEnv(k,ktr) = tracerEnv(k,ktr)- |
tracerEnv(k,ktr) = tracerEnv(k,ktr)- |
374 |
& (mda(k)*(Pda(k,ktr)-Paa(k,ktr)))*dt*recip_drF(k) |
& (mda(k)*(Pda(k,ktr)-Paa(k,ktr)))*dt*recip_drF(k) |
375 |
ENDDO |
ENDDO |
376 |
c |
|
377 |
c now do inner points if there are any |
C now do inner points if there are any |
378 |
c |
|
379 |
CML if(Maxdepth-k.gt.1) then |
CML if(Maxdepth-k.gt.1) then |
380 |
CML This if statement is superfluous |
CML This if statement is superfluous |
381 |
CML IF ( k .LT. Maxdepth-1 ) THEN |
CML IF ( k .LT. Maxdepth-1 ) THEN |
384 |
DO k2=k+1,kmx |
DO k2=k+1,kmx |
385 |
k2m1 = max(k,k2-1) |
k2m1 = max(k,k2-1) |
386 |
k2p1 = max(k2+1,maxDepth) |
k2p1 = max(k2+1,maxDepth) |
387 |
c |
|
388 |
DO ktr = 1,nTracerInUse |
DO ktr = 1,nTracerInUse |
389 |
tracerEnv(k2,ktr) = tracerEnv(k2,ktr) + |
tracerEnv(k2,ktr) = tracerEnv(k2,ktr) + |
390 |
& (mda(k2m1)*(Pda(k2m1,ktr)-Paa(k2m1,ktr)) |
& (mda(k2m1)*(Pda(k2m1,ktr)-Paa(k2m1,ktr)) |
394 |
ENDDO |
ENDDO |
395 |
CML This if statement is superfluous |
CML This if statement is superfluous |
396 |
CML ENDIF |
CML ENDIF |
397 |
C |
|
398 |
C bottom point |
C bottom point |
399 |
C |
|
400 |
DO ktr=1,nTracerInUse |
DO ktr=1,nTracerInUse |
401 |
tracerEnv(kmx+1,ktr) = tracerEnv(kmx+1,ktr)+ |
tracerEnv(kmx+1,ktr) = tracerEnv(kmx+1,ktr)+ |
402 |
& mda(kmx)*(Pda(kmx,ktr)-Paa(kmx,ktr))*dt*recip_drF(kmx+1) |
& mda(kmx)*(Pda(kmx,ktr)-Paa(kmx,ktr))*dt*recip_drF(kmx+1) |
403 |
ENDDO |
ENDDO |
404 |
c |
|
405 |
c set the environmental temp and salinity to equal new fields |
C set the environmental temp and salinity to equal new fields |
406 |
c |
|
407 |
DO ktr=1,nTracerInUse |
DO ktr=1,nTracerInUse |
408 |
DO k2=1,kmx |
DO k2=1,kmx |
409 |
paa(k2,ktr) = tracerEnv(k2+1,ktr) |
paa(k2,ktr) = tracerEnv(k2+1,ktr) |
410 |
ENDDO |
ENDDO |
411 |
ENDDO |
ENDDO |
412 |
c |
|
413 |
c end loop on number of time integration steps |
C end loop on number of time integration steps |
414 |
c |
|
415 |
enddo |
enddo |
416 |
ENDDO |
ENDDO |
417 |
999 continue |
999 continue |
418 |
C |
|
419 |
C count convection event in this grid cell |
C count convection event in this grid cell |
420 |
C |
|
421 |
OPPSconvectCount(I,J,K,bi,bj) = |
OPPSconvectCount(I,J,K,bi,bj) = |
422 |
& OPPSconvectCount(I,J,K,bi,bj) + 1. _d 0 |
& OPPSconvectCount(I,J,K,bi,bj) + 1. _d 0 |
423 |
C |
|
424 |
C jump here if k = maxdepth or if level not unstable, go to next |
C jump here if k = maxdepth or if level not unstable, go to next |
425 |
C profile point |
C profile point |
426 |
C |
|
427 |
1000 continue |
1000 continue |
428 |
c |
|
|
C |
|
429 |
C end of k-loop |
C end of k-loop |
430 |
C |
|
431 |
ENDDO |
ENDDO |
432 |
|
|
433 |
C-- End IF (DIFFERENT_MULTIPLE) |
C-- End IF (DIFFERENT_MULTIPLE) |
435 |
|
|
436 |
RETURN |
RETURN |
437 |
END |
END |
438 |
_RL FUNCTION STATE1(sLoc,tLoc,I,J,KREF,bi,bj,mythid) |
|
439 |
|
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
440 |
|
|
441 |
|
_RL FUNCTION STATE1( sLoc, tLoc, i, j, kRef, bi, bj, myThid ) |
442 |
|
|
443 |
C !DESCRIPTION: \bv |
C !DESCRIPTION: \bv |
444 |
C *===============================================================* |
C *===============================================================* |
445 |
C | o SUBROUTINE STATE1 |
C | o SUBROUTINE STATE1 |
456 |
#include "SIZE.h" |
#include "SIZE.h" |
457 |
#include "EEPARAMS.h" |
#include "EEPARAMS.h" |
458 |
#include "PARAMS.h" |
#include "PARAMS.h" |
|
#include "EOS.h" |
|
459 |
#include "GRID.h" |
#include "GRID.h" |
460 |
#include "DYNVARS.h" |
#include "DYNVARS.h" |
461 |
|
|
462 |
C !INPUT/OUTPUT PARAMETERS: |
C !INPUT/OUTPUT PARAMETERS: |
463 |
C == Routine arguments == |
C == Routine arguments == |
464 |
INTEGER I,J,kRef,bi,bj,myThid |
INTEGER i, j, kRef, bi, bj, myThid |
465 |
_RL tLoc,sLoc |
_RL tLoc, sLoc |
466 |
|
|
467 |
C !LOCAL VARIABLES: |
C !LOCAL VARIABLES: |
468 |
C == Local variables == |
C == Local variables == |
469 |
_RL rhoLoc, dRho |
_RL rhoLoc |
470 |
_RL pLoc |
_RL pLoc |
|
_RL t1, t2, t3, t4, s1, s3o2, p1, p2, sp5, p1t1 |
|
|
_RL ct, sa, sqrtsa, p |
|
|
_RL rfresh, rsalt, rhoP0 |
|
|
_RL bMfresh, bMsalt, bMpres, BulkMod |
|
|
_RL rhoNum, rhoDen, den, epsln |
|
|
PARAMETER ( epsln = 0.D0 ) |
|
|
|
|
|
character*(max_len_mbuf) msgbuf |
|
471 |
|
|
472 |
CMLC estimate pressure from depth at cell centers |
CMLC estimate pressure from depth at cell centers |
473 |
CML mtoSI = gravity*rhoConst |
CML mtoSI = gravity*rhoConst |
474 |
CML pLoc = ABS(rC(kRef))*mtoSI |
CML pLoc = ABS(rC(kRef))*mtoSI |
475 |
|
|
476 |
IF ( buoyancyRelation .EQ. 'OCEANIC' ) THEN |
IF ( usingZCoords ) THEN |
477 |
C in Z coordinates the pressure is rho0 * (hydrostatic) Potential |
C in Z coordinates the pressure is rho0 * (hydrostatic) Potential |
478 |
IF ( useDynP_inEos_Zc ) THEN |
IF ( useDynP_inEos_Zc ) THEN |
479 |
C---------- |
C---------- |
487 |
ELSE |
ELSE |
488 |
pLoc = -rhoConst*rC(kRef)*gravity*maskC(i,j,kRef,bi,bj) |
pLoc = -rhoConst*rC(kRef)*gravity*maskC(i,j,kRef,bi,bj) |
489 |
ENDIF |
ENDIF |
490 |
ELSEIF ( buoyancyRelation .EQ. 'OCEANICP' ) THEN |
ELSEIF ( usingPCoords ) THEN |
491 |
C in P coordinates the pressure is just the coordinate of |
C in P coordinates the pressure is just the coordinate of |
492 |
C the tracer point |
C the tracer point |
493 |
pLoc = rC(kRef)* maskC(i,j,kRef,bi,bj) |
pLoc = rC(kRef)* maskC(i,j,kRef,bi,bj) |
494 |
ENDIF |
ENDIF |
495 |
|
|
496 |
rhoLoc = 0. _d 0 |
CALL FIND_RHO_SCALAR( tLoc, sLoc, pLoc, rhoLoc, myThid ) |
497 |
rhoP0 = 0. _d 0 |
STATE1 = rhoLoc |
|
bulkMod = 0. _d 0 |
|
|
rfresh = 0. _d 0 |
|
|
rsalt = 0. _d 0 |
|
|
bMfresh = 0. _d 0 |
|
|
bMsalt = 0. _d 0 |
|
|
bMpres = 0. _d 0 |
|
|
rhoNum = 0. _d 0 |
|
|
rhoDen = 0. _d 0 |
|
|
den = 0. _d 0 |
|
|
|
|
|
t1 = tLoc |
|
|
t2 = t1*t1 |
|
|
t3 = t2*t1 |
|
|
t4 = t3*t1 |
|
|
|
|
|
s1 = sLoc |
|
|
|
|
|
IF ( equationOfState .EQ. 'LINEAR' ) THEN |
|
|
|
|
|
dRho = rhoNil-rhoConst |
|
|
rhoLoc=rhoNil* ( |
|
|
& sBeta *(sLoc-sRef(kRef)) |
|
|
& - tAlpha*(tLoc-tRef(KREF)) ) + dRho |
|
|
|
|
|
ELSEIF (equationOfState.EQ.'POLY3') THEN |
|
|
|
|
|
C this is not correct, there is a field eosSig0 which should be use here |
|
|
C but I DO not intent to include the reference level in this routine |
|
|
WRITE(*,'(a)') |
|
|
& ' FIND_RHO_SCALAR: for POLY3, the density is not' |
|
|
WRITE(*,'(a)') |
|
|
& ' computed correctly in this routine' |
|
|
rhoLoc = 0. _d 0 |
|
|
|
|
|
ELSEIF ( equationOfState(1:5).EQ.'JMD95' |
|
|
& .OR. equationOfState.EQ.'UNESCO' ) THEN |
|
|
C nonlinear equation of state in pressure coordinates |
|
|
|
|
|
s3o2 = s1*SQRT(s1) |
|
|
|
|
|
p1 = pLoc*SItoBar |
|
|
p2 = p1*p1 |
|
|
|
|
|
C density of freshwater at the surface |
|
|
rfresh = |
|
|
& eosJMDCFw(1) |
|
|
& + eosJMDCFw(2)*t1 |
|
|
& + eosJMDCFw(3)*t2 |
|
|
& + eosJMDCFw(4)*t3 |
|
|
& + eosJMDCFw(5)*t4 |
|
|
& + eosJMDCFw(6)*t4*t1 |
|
|
C density of sea water at the surface |
|
|
rsalt = |
|
|
& s1*( |
|
|
& eosJMDCSw(1) |
|
|
& + eosJMDCSw(2)*t1 |
|
|
& + eosJMDCSw(3)*t2 |
|
|
& + eosJMDCSw(4)*t3 |
|
|
& + eosJMDCSw(5)*t4 |
|
|
& ) |
|
|
& + s3o2*( |
|
|
& eosJMDCSw(6) |
|
|
& + eosJMDCSw(7)*t1 |
|
|
& + eosJMDCSw(8)*t2 |
|
|
& ) |
|
|
& + eosJMDCSw(9)*s1*s1 |
|
|
|
|
|
rhoP0 = rfresh + rsalt |
|
|
|
|
|
C secant bulk modulus of fresh water at the surface |
|
|
bMfresh = |
|
|
& eosJMDCKFw(1) |
|
|
& + eosJMDCKFw(2)*t1 |
|
|
& + eosJMDCKFw(3)*t2 |
|
|
& + eosJMDCKFw(4)*t3 |
|
|
& + eosJMDCKFw(5)*t4 |
|
|
C secant bulk modulus of sea water at the surface |
|
|
bMsalt = |
|
|
& s1*( eosJMDCKSw(1) |
|
|
& + eosJMDCKSw(2)*t1 |
|
|
& + eosJMDCKSw(3)*t2 |
|
|
& + eosJMDCKSw(4)*t3 |
|
|
& ) |
|
|
& + s3o2*( eosJMDCKSw(5) |
|
|
& + eosJMDCKSw(6)*t1 |
|
|
& + eosJMDCKSw(7)*t2 |
|
|
& ) |
|
|
C secant bulk modulus of sea water at pressure p |
|
|
bMpres = |
|
|
& p1*( eosJMDCKP(1) |
|
|
& + eosJMDCKP(2)*t1 |
|
|
& + eosJMDCKP(3)*t2 |
|
|
& + eosJMDCKP(4)*t3 |
|
|
& ) |
|
|
& + p1*s1*( eosJMDCKP(5) |
|
|
& + eosJMDCKP(6)*t1 |
|
|
& + eosJMDCKP(7)*t2 |
|
|
& ) |
|
|
& + p1*s3o2*eosJMDCKP(8) |
|
|
& + p2*( eosJMDCKP(9) |
|
|
& + eosJMDCKP(10)*t1 |
|
|
& + eosJMDCKP(11)*t2 |
|
|
& ) |
|
|
& + p2*s1*( eosJMDCKP(12) |
|
|
& + eosJMDCKP(13)*t1 |
|
|
& + eosJMDCKP(14)*t2 |
|
|
& ) |
|
|
|
|
|
bulkMod = bMfresh + bMsalt + bMpres |
|
|
|
|
|
C density of sea water at pressure p |
|
|
rhoLoc = rhoP0/(1. _d 0 - p1/bulkMod) - rhoConst |
|
|
|
|
|
ELSEIF ( equationOfState.EQ.'MDJWF' ) THEN |
|
|
|
|
|
sp5 = SQRT(s1) |
|
|
|
|
|
p1 = pLoc*SItodBar |
|
|
p1t1 = p1*t1 |
|
|
|
|
|
rhoNum = eosMDJWFnum(0) |
|
|
& + t1*(eosMDJWFnum(1) |
|
|
& + t1*(eosMDJWFnum(2) + eosMDJWFnum(3)*t1) ) |
|
|
& + s1*(eosMDJWFnum(4) |
|
|
& + eosMDJWFnum(5)*t1 + eosMDJWFnum(6)*s1) |
|
|
& + p1*(eosMDJWFnum(7) + eosMDJWFnum(8)*t2 |
|
|
& + eosMDJWFnum(9)*s1 |
|
|
& + p1*(eosMDJWFnum(10) + eosMDJWFnum(11)*t2) ) |
|
|
|
|
|
|
|
|
den = eosMDJWFden(0) |
|
|
& + t1*(eosMDJWFden(1) |
|
|
& + t1*(eosMDJWFden(2) |
|
|
& + t1*(eosMDJWFden(3) + t1*eosMDJWFden(4) ) ) ) |
|
|
& + s1*(eosMDJWFden(5) |
|
|
& + t1*(eosMDJWFden(6) |
|
|
& + eosMDJWFden(7)*t2) |
|
|
& + sp5*(eosMDJWFden(8) + eosMDJWFden(9)*t2) ) |
|
|
& + p1*(eosMDJWFden(10) |
|
|
& + p1t1*(eosMDJWFden(11)*t2 + eosMDJWFden(12)*p1) ) |
|
|
|
|
|
rhoDen = 1.0/(epsln+den) |
|
|
|
|
|
rhoLoc = rhoNum*rhoDen - rhoConst |
|
|
|
|
|
ELSEIF( equationOfState .EQ. 'TEOS10' ) THEN |
|
|
|
|
|
ct = tLoc |
|
|
sa = sLoc |
|
|
IF ( sa .GT. 0. _d 0 ) THEN |
|
|
sqrtsa = SQRT(sa) |
|
|
ELSE |
|
|
sa = 0. _d 0 |
|
|
sqrtsa = 0. _d 0 |
|
|
ENDIF |
|
|
p = pLoc*SItodBar |
|
|
|
|
|
rhoNum = teos(01) |
|
|
& + ct*(teos(02) + ct*(teos(03) + teos(04)*ct)) |
|
|
& + sa*(teos(05) + ct*(teos(06) + teos(07)*ct) |
|
|
& + sqrtsa*(teos(08) + ct*(teos(09) |
|
|
& + ct*(teos(10) + teos(11)*ct)))) |
|
|
& + p*(teos(12) + ct*(teos(13) + teos(14)*ct) |
|
|
& + sa*(teos(15) + teos(16)*ct) |
|
|
& + p*(teos(17) + ct*(teos(18) + teos(19)*ct) + teos(20)*sa)) |
|
|
|
|
|
den = teos(21) |
|
|
& + ct*(teos(22) + ct*(teos(23) + ct*(teos(24) + teos(25)*ct))) |
|
|
& + sa*(teos(26) + ct*(teos(27) + ct*(teos(28) |
|
|
& + ct*(teos(29) + teos(30)*ct))) |
|
|
& + teos(36)*sa |
|
|
% + sqrtsa*(teos(31) + ct*(teos(32) + ct*(teos(33) |
|
|
& + ct*(teos(34) + teos(35)*ct))))) |
|
|
% + p*(teos(37) + ct*(teos(38) + ct*(teos(39) + teos(40)*ct)) |
|
|
% + sa*(teos(41) + teos(42)*ct) |
|
|
% + p*(teos(43) + ct*(teos(44) + teos(45)*ct + teos(46)*sa) |
|
|
% + p*(teos(47) + teos(48)*ct))) |
|
|
|
|
|
|
|
|
rhoDen = 1.0/(epsln+den) |
|
|
|
|
|
rhoLoc = rhoNum*rhoDen |
|
|
|
|
|
ELSEIF( equationOfState .EQ. 'IDEALG' ) THEN |
|
|
C |
|
|
ELSE |
|
|
WRITE(msgbuf,'(3A)') |
|
|
& ' STATE1 : equationOfState = "', |
|
|
& equationOfState,'"' |
|
|
CALL PRINT_ERROR( msgbuf, mythid ) |
|
|
STOP 'ABNORMAL END: S/R STATE1 in OPPS_CALC' |
|
|
ENDIF |
|
|
|
|
|
state1 = rhoLoc + rhoConst |
|
498 |
|
|
499 |
#endif /* ALLOW_OPPS */ |
#endif /* ALLOW_OPPS */ |
500 |
RETURN |
RETURN |
501 |
END |
END |
502 |
|
|
|
|
|
|
#undef OPPS_ORGCODE |
|
503 |
#ifdef OPPS_ORGCODE |
#ifdef OPPS_ORGCODE |
504 |
c Listed below is the subroutine for use in parallel 3-d circulation code. |
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
505 |
c It has been used in the parallel semtner-chervin code and is now being used |
|
506 |
c In the POP code. The subroutine is called nlopps (long story to explain why). |
C Listed below is the subroutine for use in parallel 3-d circulation code. |
507 |
|
C It has been used in the parallel semtner-chervin code and is now being used |
508 |
c I've attached the version of lopps that we've been using in the simulations. |
C In the POP code. The subroutine is called nlopps (long story to explain why). |
509 |
c There is one common block that is different from the standard model commons |
|
510 |
c (countc) and it is not needed if the array convadj is not used. The routine |
C I've attached the version of lopps that we've been using in the simulations. |
511 |
c does need "kmp" which is why the boundc common is included. For massively |
C There is one common block that is different from the standard model commons |
512 |
c parallel codes (like POP) we think this will work well when converted from a |
C (countc) and it is not needed if the array convadj is not used. The routine |
513 |
c "slab" (i=is,ie) to a column, which just means removing the "do i=is,ie" loop. c There are differences between this |
C does need "kmp" which is why the boundc common is included. For massively |
514 |
c code and the 1-d code and the earlier scheme implemented in 3-d models. These c differences are described below. |
C parallel codes (like POP) we think this will work well when converted from a |
515 |
|
C "slab" (i=is,ie) to a column, which just means removing the "do i=is,ie" loop. c There are differences between this |
516 |
|
C code and the 1-d code and the earlier scheme implemented in 3-d models. These c differences are described below. |
517 |
|
|
518 |
|
|
519 |
subroutine nlopps(j,is,ie,ta,sa,gcmdz) |
subroutine nlopps(j,is,ie,ta,sa,gcmdz) |
520 |
c |
|
521 |
parameter (imt = 361 , jmt = 301 , km = 30 ) |
parameter (imt = 361 , jmt = 301 , km = 30 ) |
|
c |
|
|
c Nlopps: E. Skyllingstad and T. Paluszkiewicz |
|
|
c |
|
|
c Version: December 11, 1996 |
|
|
c |
|
|
c Nlopps: This version of lopps is significantly different from |
|
|
c the original code developed by R. Romea and T. Paluskiewicz. The |
|
|
c code uses a flux constraint to control the change in T and S at |
|
|
c each grid level. First, a plume profile of T,S, and W are |
|
|
c determined using the standard plume model, but with a detraining |
|
|
c mass instead of entraining. Thus, the T and S plume |
|
|
c characteristics still change, but the plume contracts in size |
|
|
c rather than expanding ala classical entraining plumes. This |
|
|
c is heuristically more in line with large eddy simulation results. |
|
|
c At each grid level, the convergence of plume velocity determines |
|
|
c the flux of T and S, which is conserved by using an upstream |
|
|
c advection. The vertical velocity is balanced so that the area |
|
|
c weighted upward velocity equals the area weighted downdraft |
|
|
c velocity, ensuring mass conservation. The present implementation |
|
|
c adjusts the plume for a time period equal to the time for 1/2 of |
|
|
c the mass of the fastest moving level to move downward. As a |
|
|
c consequence, the model does not completely adjust the profile at |
|
|
c each model time step, but provides a smooth adjustment over time. |
|
|
c |
|
|
c |
|
522 |
|
|
523 |
|
C Nlopps: E. Skyllingstad and T. Paluszkiewicz |
524 |
|
|
525 |
c |
C Version: December 11, 1996 |
526 |
|
|
527 |
|
C Nlopps: This version of lopps is significantly different from |
528 |
|
C the original code developed by R. Romea and T. Paluskiewicz. The |
529 |
|
C code uses a flux constraint to control the change in T and S at |
530 |
|
C each grid level. First, a plume profile of T,S, and W are |
531 |
|
C determined using the standard plume model, but with a detraining |
532 |
|
C mass instead of entraining. Thus, the T and S plume |
533 |
|
C characteristics still change, but the plume contracts in size |
534 |
|
C rather than expanding ala classical entraining plumes. This |
535 |
|
C is heuristically more in line with large eddy simulation results. |
536 |
|
C At each grid level, the convergence of plume velocity determines |
537 |
|
C the flux of T and S, which is conserved by using an upstream |
538 |
|
C advection. The vertical velocity is balanced so that the area |
539 |
|
C weighted upward velocity equals the area weighted downdraft |
540 |
|
C velocity, ensuring mass conservation. The present implementation |
541 |
|
C adjusts the plume for a time period equal to the time for 1/2 of |
542 |
|
C the mass of the fastest moving level to move downward. As a |
543 |
|
C consequence, the model does not completely adjust the profile at |
544 |
|
C each model time step, but provides a smooth adjustment over time. |
545 |
|
|
546 |
c include "params.h" |
c include "params.h" |
547 |
c include "plume_fast_inc.h" |
c include "plume_fast_inc.h" |
551 |
real ta(imt,km),sa(imt,km),gcmdz(km),dz(km) |
real ta(imt,km),sa(imt,km),gcmdz(km),dz(km) |
552 |
real pdensity,wsqr,oldflux,newflux,entrainrate,adtemp |
real pdensity,wsqr,oldflux,newflux,entrainrate,adtemp |
553 |
REAL Del,D,dza1,dza2,kd,kd1,Smix,Thmix,PlumeS,PlumeT,PlumeD |
REAL Del,D,dza1,dza2,kd,kd1,Smix,Thmix,PlumeS,PlumeT,PlumeD |
|
c |
|
|
c |
|
554 |
|
|
555 |
INTEGER i,j,k |
INTEGER i,j,k |
556 |
clfh |
Clfh |
557 |
integer is,ie,k2 |
integer is,ie,k2 |
558 |
clfh |
Clfh |
559 |
REAL D1,D2,state1,Density |
REAL D1,D2,state1,Density |
560 |
REAL dz1,dz2 |
REAL dz1,dz2 |
561 |
REAL radius,StartingFlux |
REAL radius,StartingFlux |
563 |
real wda(km),tda(km),sda(km),mda(km) |
real wda(km),tda(km),sda(km),mda(km) |
564 |
real dtts,dt,sumo,sumn |
real dtts,dt,sumo,sumn |
565 |
integer ntime,nn,kmx,ic |
integer ntime,nn,kmx,ic |
566 |
c |
|
|
c |
|
567 |
LOGICAL debug,done |
LOGICAL debug,done |
568 |
INTEGER MAX_ABE_ITERATIONS |
INTEGER MAX_ABE_ITERATIONS |
569 |
PARAMETER(MAX_ABE_ITERATIONS=1) |
PARAMETER(MAX_ABE_ITERATIONS=1) |
587 |
REAL PlumeEntrainment(km) |
REAL PlumeEntrainment(km) |
588 |
REAL GridThickness(km) |
REAL GridThickness(km) |
589 |
|
|
590 |
c |
C input kmp through a common block |
591 |
c input kmp through a common block |
|
|
c |
|
592 |
common / boundc / wsx(imt,jmt),wsy(imt,jmt),hfs(imt,jmt), |
common / boundc / wsx(imt,jmt),wsy(imt,jmt),hfs(imt,jmt), |
593 |
1 ple(imt,jmt),kmp(imt,jmt),kmq(imt,jmt) |
1 ple(imt,jmt),kmp(imt,jmt),kmq(imt,jmt) |
594 |
cwmseas |
cwmseas |
595 |
& ,wsx1(imt,jmt),wsy1(imt,jmt) |
& ,wsx1(imt,jmt),wsy1(imt,jmt) |
596 |
1 ,wsx2(imt,jmt),wsy2(imt,jmt) |
1 ,wsx2(imt,jmt),wsy2(imt,jmt) |
597 |
c |
|
598 |
c input the variables through a common |
C input the variables through a common |
599 |
c |
|
600 |
logical problem |
logical problem |
601 |
common /countc/ convadj(imt,jmt,km),ics,depth(km),problem |
common /countc/ convadj(imt,jmt,km),ics,depth(km),problem |
602 |
|
|
603 |
|
|
604 |
c-----may want to setup an option to get this only on first call |
C-----may want to setup an option to get this only on first call |
605 |
c otherwise it is repetive |
C otherwise it is repetive |
606 |
c griddz is initialize by call to setupgrid |
C griddz is initialize by call to setupgrid |
|
c |
|
|
c |
|
607 |
|
|
608 |
dtts = 2400 |
dtts = 2400 |
609 |
c |
|
610 |
do k=1,km |
do k=1,km |
611 |
dz(k) = 0.01*gcmdz(k) |
dz(k) = 0.01*gcmdz(k) |
612 |
enddo |
enddo |
613 |
c |
|
614 |
do k=1,km |
do k=1,km |
615 |
GridThickness(k) = dz(k) |
GridThickness(k) = dz(k) |
616 |
enddo |
enddo |
617 |
c |
|
618 |
c modified to loop over slab |
C modified to loop over slab |
619 |
c |
|
620 |
DO i=is,ie |
DO i=is,ie |
621 |
|
|
622 |
numgridpoints=kmp(i,j) |
numgridpoints=kmp(i,j) |
623 |
c |
|
624 |
c go to next column if only 1 grid point or on land |
C go to next column if only 1 grid point or on land |
625 |
c |
|
626 |
if(numgridpoints.le.1) goto 1100 |
if(numgridpoints.le.1) goto 1100 |
627 |
c |
|
628 |
c loop over depth |
C loop over depth |
629 |
c |
|
|
c |
|
630 |
debug = .false. |
debug = .false. |
631 |
c |
|
632 |
c first save copy of initial profile |
C first save copy of initial profile |
633 |
c |
|
634 |
DO k=1,NumGridPoints |
DO k=1,NumGridPoints |
635 |
stemp(k)=sa(i,k) |
stemp(k)=sa(i,k) |
636 |
ttemp(k)=ta(i,k) |
ttemp(k)=ta(i,k) |
637 |
c |
|
638 |
c do a check of t and s range, if out of bounds set flag |
C do a check of t and s range, if out of bounds set flag |
639 |
c |
|
640 |
if(problem) then |
if(problem) then |
641 |
write(0,*)"Code in trouble before this nlopps call" |
write(0,*)"Code in trouble before this nlopps call" |
642 |
return |
return |
643 |
endif |
endif |
644 |
c |
|
645 |
if(sa(i,k).gt.40..or.ta(i,k).lt.-4.0) then |
if(sa(i,k).gt.40..or.ta(i,k).lt.-4.0) then |
646 |
problem = .true. |
problem = .true. |
647 |
write(0,*)"t out of range at j ",j |
write(0,*)"t out of range at j ",j |
656 |
endif |
endif |
657 |
|
|
658 |
DO k=1,NumGridPoints-1 |
DO k=1,NumGridPoints-1 |
659 |
c |
|
660 |
c initialize the plume T,S,density, and w velocity |
C initialize the plume T,S,density, and w velocity |
661 |
c |
|
662 |
Sd(k)=stemp(k) |
Sd(k)=stemp(k) |
663 |
Td(k)=ttemp(k) |
Td(k)=ttemp(k) |
664 |
Dd(k)=state1(stemp(k),ttemp(k),k) |
Dd(k)=state1(stemp(k),ttemp(k),k) |
665 |
De(k)=Dd(k) |
De(k)=Dd(k) |
666 |
c Wd(k)=VERTICAL_VELOCITY |
c Wd(k)=VERTICAL_VELOCITY |
667 |
c |
|
668 |
c guess at initial top grid cell vertical velocity |
C guess at initial top grid cell vertical velocity |
669 |
c |
|
670 |
Wd(k) = 0.03 |
Wd(k) = 0.03 |
671 |
c |
|
672 |
c these estimates of initial plume velocity based on plume size and |
C these estimates of initial plume velocity based on plume size and |
673 |
c top grid cell water mass |
C top grid cell water mass |
674 |
c |
|
675 |
c Wd(k) = 0.5*dz(k)/(dtts*FRACTIONAL_AREA) |
c Wd(k) = 0.5*dz(k)/(dtts*FRACTIONAL_AREA) |
676 |
c Wd(k) = 0.5*dz(k)/dtts |
c Wd(k) = 0.5*dz(k)/dtts |
677 |
c |
|
678 |
wsqr=Wd(k)*Wd(k) |
wsqr=Wd(k)*Wd(k) |
679 |
PlumeEntrainment(k) = 0.0 |
PlumeEntrainment(k) = 0.0 |
680 |
c |
|
|
c |
|
|
c |
|
681 |
if(debug) write(0,*) 'Doing old lowerparcel' |
if(debug) write(0,*) 'Doing old lowerparcel' |
682 |
radius=PlumeRadius |
radius=PlumeRadius |
683 |
StartingFlux=radius*radius*Wd(k)*Dd(k) |
StartingFlux=radius*radius*Wd(k)*Dd(k) |
688 |
D1=state1(Sd(k2),Td(k2),k2+1) |
D1=state1(Sd(k2),Td(k2),k2+1) |
689 |
D2=state1(stemp(k2+1),ttemp(k2+1),k2+1) |
D2=state1(stemp(k2+1),ttemp(k2+1),k2+1) |
690 |
De(k2+1)=D2 |
De(k2+1)=D2 |
691 |
c |
|
692 |
c To start downward, parcel has to initially be heavier than environment |
C To start downward, parcel has to initially be heavier than environment |
693 |
c but after it has started moving, we continue plume until plume tke or |
C but after it has started moving, we continue plume until plume tke or |
694 |
c flux goes negative |
C flux goes negative |
695 |
c |
|
696 |
IF (D2-D1 .LT. STABILITY_THRESHOLD.or.k2.ne.k) THEN |
IF (D2-D1 .LT. STABILITY_THRESHOLD.or.k2.ne.k) THEN |
697 |
dz1=dz2 |
dz1=dz2 |
698 |
dz2=GridThickness(k2+1) |
dz2=GridThickness(k2+1) |
699 |
c |
|
700 |
c define mass flux according to eq. 4 from paper |
C define mass flux according to eq. 4 from paper |
701 |
c |
|
702 |
newflux=oldflux+e2*radius*Wd(k2)*Dd(k2)*0.50* |
newflux=oldflux+e2*radius*Wd(k2)*Dd(k2)*0.50* |
703 |
. (dz1+dz2) |
. (dz1+dz2) |
704 |
c |
|
705 |
PlumeEntrainment(k2+1) = newflux/StartingFlux |
PlumeEntrainment(k2+1) = newflux/StartingFlux |
706 |
c |
|
707 |
IF(newflux.LT.0.0) then |
IF(newflux.LT.0.0) then |
708 |
if(debug) then |
if(debug) then |
709 |
write(0,*)"Plume entrained to zero at ",k2 |
write(0,*)"Plume entrained to zero at ",k2 |
712 |
if(maxdepth.eq.k) goto 1000 |
if(maxdepth.eq.k) goto 1000 |
713 |
goto 1 |
goto 1 |
714 |
endif |
endif |
715 |
c |
|
716 |
c entrainment rate is basically a scaled mass flux dM/M |
C entrainment rate is basically a scaled mass flux dM/M |
717 |
c |
|
718 |
entrainrate = (newflux - oldflux)/newflux |
entrainrate = (newflux - oldflux)/newflux |
719 |
oldflux = newflux |
oldflux = newflux |
720 |
c |
|
721 |
c |
C mix var(s) are the average environmental values over the two grid levels |
722 |
c mix var(s) are the average environmental values over the two grid levels |
|
|
c |
|
723 |
smix=(dz1*stemp(k2)+dz2*stemp(k2+1))/(dz1+dz2) |
smix=(dz1*stemp(k2)+dz2*stemp(k2+1))/(dz1+dz2) |
724 |
thmix=(dz1*ttemp(k2)+dz2*ttemp(k2+1))/(dz1+dz2) |
thmix=(dz1*ttemp(k2)+dz2*ttemp(k2+1))/(dz1+dz2) |
725 |
c |
|
726 |
c first compute the new salinity and temperature for this level |
C first compute the new salinity and temperature for this level |
727 |
c using equations 3.6 and 3.7 from the paper |
C using equations 3.6 and 3.7 from the paper |
728 |
c |
|
|
c |
|
|
c |
|
729 |
sd(k2+1)=sd(k2) - entrainrate*(smix - sd(k2)) |
sd(k2+1)=sd(k2) - entrainrate*(smix - sd(k2)) |
730 |
td(k2+1)=td(k2) - entrainrate*(thmix - td(k2)) |
td(k2+1)=td(k2) - entrainrate*(thmix - td(k2)) |
731 |
c |
|
732 |
c |
C compute the density at this level for the buoyancy term in the |
733 |
c compute the density at this level for the buoyancy term in the |
C vertical k.e. equation |
734 |
c vertical k.e. equation |
|
|
c |
|
735 |
Dd(k2+1)=state1(Sd(k2+1),Td(k2+1),k2+1) |
Dd(k2+1)=state1(Sd(k2+1),Td(k2+1),k2+1) |
736 |
c |
|
737 |
c next, solve for the vertical velocity k.e. using combined eq. 4 |
C next, solve for the vertical velocity k.e. using combined eq. 4 |
738 |
c and eq 5 from the paper |
C and eq 5 from the paper |
739 |
c |
|
740 |
if(debug) then |
if(debug) then |
741 |
write(0,*)"Dd,De,entr,k ",Dd(k2),De(k2),entrainrate,k2 |
write(0,*)"Dd,De,entr,k ",Dd(k2),De(k2),entrainrate,k2 |
742 |
endif |
endif |
743 |
c |
|
744 |
wsqr = wsqr - wsqr*abs(entrainrate)+ 9.81* |
wsqr = wsqr - wsqr*abs(entrainrate)+ 9.81* |
745 |
. (dz1*(Dd(k2)-De(k2))/De(k2) |
. (dz1*(Dd(k2)-De(k2))/De(k2) |
746 |
. +dz2*(Dd(k2+1)-De(k2+1))/De(k2+1)) |
. +dz2*(Dd(k2+1)-De(k2+1))/De(k2+1)) |
747 |
c |
|
748 |
c if negative k.e. then plume has reached max depth, get out of loop |
C if negative k.e. then plume has reached max depth, get out of loop |
749 |
c |
|
750 |
IF(wsqr.LT.0.0)then |
IF(wsqr.LT.0.0)then |
751 |
maxdepth = k2 |
maxdepth = k2 |
752 |
if(debug) then |
if(debug) then |
756 |
goto 1 |
goto 1 |
757 |
endif |
endif |
758 |
Wd(k2+1)=sqrt(wsqr) |
Wd(k2+1)=sqrt(wsqr) |
759 |
c |
|
760 |
c compute a new radius based on the new mass flux at this grid level |
C compute a new radius based on the new mass flux at this grid level |
761 |
c |
|
762 |
radius=sqrt(newflux/(Wd(k2)*Dd(k2))) |
radius=sqrt(newflux/(Wd(k2)*Dd(k2))) |
763 |
ELSE |
ELSE |
764 |
maxdepth=k2 |
maxdepth=k2 |
766 |
GOTO 1 |
GOTO 1 |
767 |
ENDIF |
ENDIF |
768 |
ENDDO |
ENDDO |
769 |
c |
|
770 |
c plume has reached the bottom |
C plume has reached the bottom |
771 |
c |
|
772 |
MaxDepth=NumGridPoints |
MaxDepth=NumGridPoints |
773 |
c |
|
774 |
1 continue |
1 continue |
775 |
c |
|
776 |
Ad(k)=FRACTIONAL_AREA |
Ad(k)=FRACTIONAL_AREA |
777 |
IC=0 |
IC=0 |
778 |
c |
|
779 |
c start iteration on fractional area, not used in OGCM implementation |
C start iteration on fractional area, not used in OGCM implementation |
780 |
c |
|
|
c |
|
781 |
DO IC=1,Max_ABE_Iterations |
DO IC=1,Max_ABE_Iterations |
782 |
c |
|
783 |
c |
C next compute the mass flux beteen each grid box using the entrainment |
784 |
c next compute the mass flux beteen each grid box using the entrainment |
|
|
c |
|
785 |
92 continue |
92 continue |
786 |
Md(k)=Wd(k)*Ad(k) |
Md(k)=Wd(k)*Ad(k) |
787 |
c |
|
788 |
DO k2=k+1,MaxDepth |
DO k2=k+1,MaxDepth |
789 |
Md(k2)=Md(k)*PlumeEntrainment(k2) |
Md(k2)=Md(k)*PlumeEntrainment(k2) |
790 |
if(debug) then |
if(debug) then |
791 |
write(0,*)"Md, Wd, and k are ",Md(k2),Wd(k2),k2 |
write(0,*)"Md, Wd, and k are ",Md(k2),Wd(k2),k2 |
792 |
endif |
endif |
793 |
ENDDO |
ENDDO |
794 |
c |
|
795 |
c Now move on to calculate new temperature using flux from |
C Now move on to calculate new temperature using flux from |
796 |
c Td, Sd, Wd, ta, sa, and we. Values for these variables are at |
C Td, Sd, Wd, ta, sa, and we. Values for these variables are at |
797 |
c center of grid cell, use weighted average to get boundary values |
C center of grid cell, use weighted average to get boundary values |
798 |
c |
|
799 |
c use a timestep limited by the GCM model timestep and the maximum plume |
C use a timestep limited by the GCM model timestep and the maximum plume |
800 |
c velocity (CFL criteria) |
C velocity (CFL criteria) |
801 |
c |
|
802 |
c |
C calculate the weighted wd, td, and sd |
803 |
c calculate the weighted wd, td, and sd |
|
|
c |
|
804 |
dt = dtts |
dt = dtts |
805 |
do k2=k,maxdepth-1 |
do k2=k,maxdepth-1 |
806 |
dt = min(dt,dz(k2)/wd(k2)) |
dt = min(dt,dz(k2)/wd(k2)) |
807 |
c |
|
808 |
c time integration will be integer number of steps to get one |
C time integration will be integer number of steps to get one |
809 |
c gcm time step |
C gcm time step |
810 |
c |
|
811 |
ntime = nint(0.5*int(dtts/dt)) |
ntime = nint(0.5*int(dtts/dt)) |
812 |
if(ntime.eq.0) then |
if(ntime.eq.0) then |
813 |
ntime = 1 |
ntime = 1 |
814 |
endif |
endif |
815 |
c |
|
816 |
c make sure area weighted vertical velocities match; in other words |
C make sure area weighted vertical velocities match; in other words |
817 |
c make sure mass in equals mass out at the intersection of each grid |
C make sure mass in equals mass out at the intersection of each grid |
818 |
c cell. |
C cell. |
819 |
c |
|
820 |
mda(k2) = (md(k2)*dz(k2)+md(k2+1)*dz(k2+1))/ |
mda(k2) = (md(k2)*dz(k2)+md(k2+1)*dz(k2+1))/ |
821 |
* (dz(k2)+dz(k2+1)) |
* (dz(k2)+dz(k2+1)) |
822 |
c |
|
823 |
wda(k2) = (wd(k2)*dz(k2)+wd(k2+1)*dz(k2+1))/ |
wda(k2) = (wd(k2)*dz(k2)+wd(k2+1)*dz(k2+1))/ |
824 |
* (dz(k2)+dz(k2+1)) |
* (dz(k2)+dz(k2+1)) |
825 |
c |
|
826 |
tda(k2) = td(k2) |
tda(k2) = td(k2) |
827 |
sda(k2) = sd(k2) |
sda(k2) = sd(k2) |
828 |
c |
|
829 |
taa(k2) = ttemp(k2+1) |
taa(k2) = ttemp(k2+1) |
830 |
saa(k2) = stemp(k2+1) |
saa(k2) = stemp(k2+1) |
831 |
c |
|
832 |
enddo |
enddo |
833 |
dt = min(dt,dtts) |
dt = min(dt,dtts) |
834 |
if(debug) then |
if(debug) then |
836 |
endif |
endif |
837 |
tda(maxdepth) = td(maxdepth) |
tda(maxdepth) = td(maxdepth) |
838 |
sda(maxdepth) = sd(maxdepth) |
sda(maxdepth) = sd(maxdepth) |
839 |
c |
|
840 |
c do top and bottom points first |
C do top and bottom points first |
841 |
c |
|
842 |
kmx = maxdepth-1 |
kmx = maxdepth-1 |
843 |
do nn=1,ntime |
do nn=1,ntime |
844 |
|
|
845 |
ttemp(k) = ttemp(k)- |
ttemp(k) = ttemp(k)- |
846 |
* (mda(k)*(tda(k)-taa(k)))*dt*recip_drF(k) |
* (mda(k)*(tda(k)-taa(k)))*dt*recip_drF(k) |
847 |
c |
|
848 |
stemp(k) = stemp(k)- |
stemp(k) = stemp(k)- |
849 |
* (mda(k)*(sda(k)-saa(k)))*dt*recip_drF(k) |
* (mda(k)*(sda(k)-saa(k)))*dt*recip_drF(k) |
850 |
c |
|
851 |
c |
C now do inner points if there are any |
852 |
c now do inner points if there are any |
|
|
c |
|
853 |
if(Maxdepth-k.gt.1) then |
if(Maxdepth-k.gt.1) then |
854 |
do k2=k+1,Maxdepth-1 |
do k2=k+1,Maxdepth-1 |
855 |
c |
|
856 |
ttemp(k2) = ttemp(k2) + |
ttemp(k2) = ttemp(k2) + |
857 |
* (mda(k2-1)*(tda(k2-1)-taa(k2-1))- |
* (mda(k2-1)*(tda(k2-1)-taa(k2-1))- |
858 |
* mda(k2)*(tda(k2)-taa(k2))) |
* mda(k2)*(tda(k2)-taa(k2))) |
859 |
* *dt*recip_drF(k2) |
* *dt*recip_drF(k2) |
860 |
|
|
|
c |
|
861 |
stemp(k2) = stemp(k2) + |
stemp(k2) = stemp(k2) + |
862 |
* (mda(k2-1)*(sda(k2-1)-saa(k2-1))- |
* (mda(k2-1)*(sda(k2-1)-saa(k2-1))- |
863 |
* mda(k2)*(sda(k2)-saa(k2))) |
* mda(k2)*(sda(k2)-saa(k2))) |
864 |
* *dt*recip_drF(k2) |
* *dt*recip_drF(k2) |
865 |
|
|
|
c |
|
866 |
enddo |
enddo |
867 |
endif |
endif |
868 |
ttemp(kmx+1) = ttemp(kmx+1)+ |
ttemp(kmx+1) = ttemp(kmx+1)+ |
869 |
* (mda(kmx)*(tda(kmx)-taa(kmx)))* |
* (mda(kmx)*(tda(kmx)-taa(kmx)))* |
870 |
* dt*recip_drF(kmx+1) |
* dt*recip_drF(kmx+1) |
871 |
c |
|
872 |
stemp(kmx+1) = stemp(kmx+1)+ |
stemp(kmx+1) = stemp(kmx+1)+ |
873 |
* (mda(kmx)*(sda(kmx)-saa(kmx)))* |
* (mda(kmx)*(sda(kmx)-saa(kmx)))* |
874 |
* dt*recip_drF(kmx+1) |
* dt*recip_drF(kmx+1) |
875 |
c |
|
876 |
c set the environmental temp and salinity to equal new fields |
C set the environmental temp and salinity to equal new fields |
877 |
c |
|
878 |
do k2=1,maxdepth-1 |
do k2=1,maxdepth-1 |
879 |
taa(k2) = ttemp(k2+1) |
taa(k2) = ttemp(k2+1) |
880 |
saa(k2) = stemp(k2+1) |
saa(k2) = stemp(k2+1) |
881 |
enddo |
enddo |
882 |
c |
|
883 |
c end loop on number of time integration steps |
C end loop on number of time integration steps |
884 |
c |
|
885 |
enddo |
enddo |
886 |
ENDDO |
ENDDO |
887 |
999 continue |
999 continue |
888 |
c |
|
889 |
c assume that it converged, so update the ta and sa with new fields |
C assume that it converged, so update the ta and sa with new fields |
890 |
c |
|
891 |
c if(i.gt.180.and.j.gt.200.and.i.lt.240) then |
c if(i.gt.180.and.j.gt.200.and.i.lt.240) then |
892 |
c write(*,*)"Converged ",i,j,k,maxdepth,ttemp(k+1),ta(i,k+1) |
c write(*,*)"Converged ",i,j,k,maxdepth,ttemp(k+1),ta(i,k+1) |
893 |
c endif |
c endif |
899 |
c if(i.gt.180.and.j.gt.200.and.i.lt.240) then |
c if(i.gt.180.and.j.gt.200.and.i.lt.240) then |
900 |
c write(*,*)"convadj ",convadj(i,j,k2) |
c write(*,*)"convadj ",convadj(i,j,k2) |
901 |
c endif |
c endif |
902 |
c |
|
903 |
c see if nlopps messed up |
C see if nlopps messed up |
904 |
c |
|
905 |
if(sa(i,k).gt.40..or.ta(i,k).lt.-4.0) then |
if(sa(i,k).gt.40..or.ta(i,k).lt.-4.0) then |
906 |
problem = .true. |
problem = .true. |
907 |
write(0,*)"t out of range at j after adjust",j |
write(0,*)"t out of range at j after adjust",j |
908 |
debug = .true. |
debug = .true. |
909 |
endif |
endif |
910 |
c |
|
911 |
enddo |
enddo |
912 |
c |
|
913 |
c jump here if k = maxdepth or if level not unstable, go to next |
C jump here if k = maxdepth or if level not unstable, go to next |
914 |
c profile point |
C profile point |
915 |
c |
|
916 |
1000 continue |
1000 continue |
917 |
c |
|
918 |
c |
C end loop on k, move on to next possible plume |
919 |
c end loop on k, move on to next possible plume |
|
|
c |
|
920 |
ENDDO |
ENDDO |
921 |
1100 continue |
1100 continue |
922 |
c |
|
923 |
c i loop |
C i loop |
924 |
c |
|
925 |
ENDDO |
ENDDO |
926 |
END |
END |
927 |
|
|