1 |
C $Header: /u/gcmpack/MITgcm/model/src/set_ref_state.F,v 1.5 2013/07/28 16:01:51 jmc Exp $ |
2 |
C $Name: $ |
3 |
|
4 |
#include "CPP_OPTIONS.h" |
5 |
|
6 |
CBOP |
7 |
C !ROUTINE: SET_REF_STATE |
8 |
C !INTERFACE: |
9 |
SUBROUTINE SET_REF_STATE( |
10 |
I myThid ) |
11 |
C !DESCRIPTION: \bv |
12 |
C *==========================================================* |
13 |
C | SUBROUTINE SET_REF_STATE |
14 |
C | o Set reference potential at level center and |
15 |
C | level interface, using tRef,sRef profiles. |
16 |
C | note: use same discretisation as in calc_phi_hyd |
17 |
C | o Set also reference stratification here (for implicit |
18 |
C | Internal Gravity Waves) and units conversion factor |
19 |
C | for vertical velocity (for Non-Hydrostatic in p) |
20 |
C | since both use also the same reference density. |
21 |
C *==========================================================* |
22 |
C \ev |
23 |
|
24 |
C !USES: |
25 |
IMPLICIT NONE |
26 |
C == Global variables == |
27 |
#include "SIZE.h" |
28 |
#include "EEPARAMS.h" |
29 |
#include "PARAMS.h" |
30 |
#include "GRID.h" |
31 |
#include "EOS.h" |
32 |
|
33 |
C !INPUT/OUTPUT PARAMETERS: |
34 |
C == Routine arguments == |
35 |
INTEGER myThid |
36 |
|
37 |
C !LOCAL VARIABLES: |
38 |
C == Local variables == |
39 |
C msgBuf :: Informational/error message buffer |
40 |
CHARACTER*(MAX_LEN_MBUF) msgBuf |
41 |
INTEGER k, ks, stdUnit |
42 |
_RL rHalf(2*Nr+1) |
43 |
_RL rhoRef(Nr), tLoc(Nr) |
44 |
_RL pLoc, rhoUp, rhoDw, rhoLoc |
45 |
_RL ddPI, conv_theta2T, thetaLoc |
46 |
CEOP |
47 |
|
48 |
_BEGIN_MASTER( myThid ) |
49 |
|
50 |
C-- Initialise: |
51 |
DO k=1,2*Nr |
52 |
phiRef(k) = 0. |
53 |
ENDDO |
54 |
stdUnit = standardMessageUnit |
55 |
|
56 |
DO k=1,Nr |
57 |
rhoRef(k) = 0. |
58 |
dBdrRef(k) = 0. |
59 |
rHalf(2*k-1) = rF(k) |
60 |
rHalf(2*k) = rC(k) |
61 |
ENDDO |
62 |
rHalf(2*Nr+1) = rF(Nr+1) |
63 |
|
64 |
DO k=1,Nr+1 |
65 |
rVel2wUnit(k) = 1. _d 0 |
66 |
wUnit2rVel(k) = 1. _d 0 |
67 |
ENDDO |
68 |
|
69 |
C-- Initialise density factor for anelastic formulation: |
70 |
DO k=1,Nr |
71 |
rhoFacC(k) = 1. _d 0 |
72 |
recip_rhoFacC(k) = 1. _d 0 |
73 |
ENDDO |
74 |
DO k=1,Nr+1 |
75 |
rhoFacF(k) = 1. _d 0 |
76 |
recip_rhoFacF(k) = 1. _d 0 |
77 |
ENDDO |
78 |
|
79 |
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
80 |
IF ( eosType.EQ.'POLY3' ) THEN |
81 |
IF ( implicitIntGravWave ) THEN |
82 |
WRITE(msgBuf,'(2A)') 'SET_REF_STATE:', |
83 |
& ' need to compute reference density for Impl.IGW' |
84 |
CALL PRINT_ERROR( msgBuf , myThid ) |
85 |
WRITE(msgBuf,'(2A)') 'SET_REF_STATE:', |
86 |
& ' but FIND_RHO_SCALAR(EOS="POLY3") not (yet) implemented' |
87 |
CALL PRINT_ERROR( msgBuf , myThid ) |
88 |
STOP 'ABNORMAL END: S/R SET_REF_STATE' |
89 |
ELSEIF ( nonHydrostatic .AND. |
90 |
& buoyancyRelation .EQ. 'OCEANICP' ) THEN |
91 |
WRITE(msgBuf,'(2A)') 'SET_REF_STATE:', |
92 |
& ' need to compute reference density for Non-Hyd' |
93 |
CALL PRINT_ERROR( msgBuf , myThid ) |
94 |
WRITE(msgBuf,'(2A)') 'SET_REF_STATE:', |
95 |
& ' but FIND_RHO_SCALAR(EOS="POLY3") not (yet) implemented' |
96 |
CALL PRINT_ERROR( msgBuf , myThid ) |
97 |
STOP 'ABNORMAL END: S/R SET_REF_STATE' |
98 |
ELSE |
99 |
WRITE(msgBuf,'(2A)') 'SET_REF_STATE:', |
100 |
& ' Unable to compute reference stratification' |
101 |
CALL PRINT_MESSAGE( msgBuf, errorMessageUnit, |
102 |
& SQUEEZE_RIGHT , myThid ) |
103 |
WRITE(msgBuf,'(2A)') 'SET_REF_STATE:', |
104 |
& ' with EOS="POLY3" ; set dBdrRef(1:Nr) to zeros' |
105 |
CALL PRINT_MESSAGE( msgBuf, errorMessageUnit, |
106 |
& SQUEEZE_RIGHT , myThid) |
107 |
ENDIF |
108 |
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
109 |
ELSEIF (buoyancyRelation .EQ. 'OCEANIC') THEN |
110 |
|
111 |
C-- Compute reference density profile and reference stratification |
112 |
DO k=1,Nr |
113 |
pLoc = -rhoConst*rC(k)*gravity |
114 |
CALL FIND_RHO_SCALAR( |
115 |
I tRef(k), sRef(k), pLoc, |
116 |
O rhoRef(k), myThid ) |
117 |
ENDDO |
118 |
|
119 |
C-- Compute reference stratification: N^2 = -(g/rho_c) * d.rho/dz @ const. p |
120 |
dBdrRef(1) = 0. _d 0 |
121 |
DO k=2,Nr |
122 |
pLoc = -rhoConst*rF(k)*gravity |
123 |
CALL FIND_RHO_SCALAR( |
124 |
I tRef(k-1), sRef(k-1), pLoc, |
125 |
O rhoUp, myThid ) |
126 |
CALL FIND_RHO_SCALAR( |
127 |
I tRef(k), sRef(k), pLoc, |
128 |
O rhoDw, myThid ) |
129 |
dBdrRef(k) = (rhoDw - rhoUp)*recip_drC(k) |
130 |
& *recip_rhoConst*gravity |
131 |
IF (eosType .EQ. 'LINEAR') THEN |
132 |
C- get more precise values (differences from above are due to machine round-off) |
133 |
dBdrRef(k) = ( sBeta *(sRef(k)-sRef(k-1)) |
134 |
& -tAlpha*(tRef(k)-tRef(k-1)) |
135 |
& )*recip_drC(k) |
136 |
& *rhoNil*recip_rhoConst*gravity |
137 |
ENDIF |
138 |
ENDDO |
139 |
|
140 |
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
141 |
ELSEIF (buoyancyRelation .EQ. 'OCEANICP') THEN |
142 |
|
143 |
C-- Compute reference density profile |
144 |
DO k=1,Nr |
145 |
pLoc = rC(k) |
146 |
CALL FIND_RHO_SCALAR( |
147 |
I tRef(k), sRef(k), pLoc, |
148 |
O rhoRef(k), myThid ) |
149 |
ENDDO |
150 |
|
151 |
C-- Compute reference stratification: -d.alpha/dp @ constant p |
152 |
dBdrRef(1) = 0. _d 0 |
153 |
DO k=1,Nr+1 |
154 |
pLoc = rF(k) |
155 |
IF ( k.GE.2 ) CALL FIND_RHO_SCALAR( |
156 |
I tRef(k-1), sRef(k-1), pLoc, |
157 |
O rhoDw, myThid ) |
158 |
IF ( k.LE.Nr ) CALL FIND_RHO_SCALAR( |
159 |
I tRef(k), sRef(k), pLoc, |
160 |
O rhoUp, myThid ) |
161 |
IF ( k.GE.2 .AND. k.LE.Nr ) THEN |
162 |
dBdrRef(k) = (rhoDw - rhoUp)*recip_drC(k) |
163 |
& / (rhoDw*rhoUp) |
164 |
rhoLoc = ( rhoDw + rhoUp )*0.5 _d 0 |
165 |
ELSEIF ( k.EQ.1 ) THEN |
166 |
rhoLoc = rhoUp |
167 |
ELSE |
168 |
rhoLoc = rhoDw |
169 |
ENDIF |
170 |
C-- Units convertion factor for vertical velocity: |
171 |
C wUnit2rVel = gravity*rhoRef : rVel [Pa/s] = wSpeed [m/s] * wUnit2rVel |
172 |
C rVel2wUnit = 1/rVel2wUnit : wSpeed [m/s] = rVel [Pa/s] * rVel2wUnit |
173 |
C note: wUnit2rVel & rVel2wUnit replace horiVertRatio & recip_horiVertRatio |
174 |
wUnit2rVel(k) = gravity*rhoLoc |
175 |
rVel2wUnit(k) = 1. _d 0 / wUnit2rVel(k) |
176 |
ENDDO |
177 |
|
178 |
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
179 |
ELSEIF (buoyancyRelation .EQ. 'ATMOSPHERIC') THEN |
180 |
|
181 |
C-- Compute reference stratification: -d.alpha/dp @ constant p |
182 |
dBdrRef(1) = 0. _d 0 |
183 |
DO k=2,Nr |
184 |
conv_theta2T = (rF(k)/atm_Po)**atm_kappa |
185 |
c dBdrRef(k) = (tRef(k) - tRef(k-1))*recip_drC(k) |
186 |
c & * conv_theta2T*atm_Rd/rF(k) |
187 |
ddPI=atm_Cp*( ((rC(k-1)/atm_Po)**atm_kappa) |
188 |
& -((rC( k )/atm_Po)**atm_kappa) ) |
189 |
dBdrRef(k) = (tRef(k) - tRef(k-1))*recip_drC(k) |
190 |
& * ddPI*recip_drC(k) |
191 |
ENDDO |
192 |
|
193 |
C-- Units convertion factor for vertical velocity: |
194 |
C wUnit2rVel = gravity/alpha : rVel [Pa/s] = wSpeed [m/s] * wUnit2rVel |
195 |
C rVel2wUnit = alpha/gravity : wSpeed [m/s] = rVel [Pa/s] * rVel2wUnit |
196 |
C with alpha = 1/rhoRef = (R.T/p) (ideal gas) |
197 |
C note: wUnit2rVel & rVel2wUnit replace horiVertRatio & recip_horiVertRatio |
198 |
DO k=1,Nr+1 |
199 |
IF ( k.EQ.1 ) THEN |
200 |
thetaLoc = tRef(k) |
201 |
ELSEIF ( k.GT.Nr ) THEN |
202 |
thetaLoc = tRef(k-1) |
203 |
ELSE |
204 |
thetaLoc = (tRef(k) + tRef(k-1))*0.5 _d 0 |
205 |
ENDIF |
206 |
IF ( thetaLoc.GT.0. _d 0 .AND. rF(k).GT.0. _d 0 ) THEN |
207 |
conv_theta2T = (rF(k)/atm_Po)**atm_kappa |
208 |
wUnit2rVel(k) = gravity |
209 |
& * rF(k)/(atm_Rd*conv_theta2T*thetaLoc) |
210 |
rVel2wUnit(k) = 1. _d 0 / wUnit2rVel(k) |
211 |
ENDIF |
212 |
ENDDO |
213 |
|
214 |
C- Compute Reference Geopotential at Half levels : |
215 |
C Tracer level k: phiRef(2k) ; Interface_W level k: phiRef(2k-1) |
216 |
|
217 |
phiRef(1) = 0. _d 0 |
218 |
IF ( select_rStar.GE.1 .OR. selectSigmaCoord.GE.1 ) THEN |
219 |
C- isothermal (theta=const) reference state |
220 |
DO k=1,Nr |
221 |
tLoc(k) = thetaConst |
222 |
ENDDO |
223 |
ELSE |
224 |
C- horizontally uniform (tRef) reference state |
225 |
DO k=1,Nr |
226 |
tLoc(k) = tRef(k) |
227 |
ENDDO |
228 |
ENDIF |
229 |
|
230 |
IF (integr_GeoPot.EQ.1) THEN |
231 |
C- Finite Volume Form, linear by half level : |
232 |
DO k=1,2*Nr |
233 |
ks = (k+1)/2 |
234 |
ddPI=atm_Cp*( ((rHalf( k )/atm_Po)**atm_kappa) |
235 |
& -((rHalf(k+1)/atm_Po)**atm_kappa) ) |
236 |
phiRef(k+1) = phiRef(k)+ddPI*tLoc(ks) |
237 |
ENDDO |
238 |
C------ |
239 |
ELSE |
240 |
C- Finite Difference Form, linear between Tracer level : |
241 |
C works with integr_GeoPot = 0, 2 or 3 |
242 |
k = 1 |
243 |
ddPI=atm_Cp*( ((rF(k)/atm_Po)**atm_kappa) |
244 |
& -((rC(k)/atm_Po)**atm_kappa) ) |
245 |
phiRef(2*k) = phiRef(1) + ddPI*tLoc(k) |
246 |
DO k=1,Nr-1 |
247 |
ddPI=atm_Cp*( ((rC( k )/atm_Po)**atm_kappa) |
248 |
& -((rC(k+1)/atm_Po)**atm_kappa) ) |
249 |
phiRef(2*k+1) = phiRef(2*k) + ddPI*0.5*tLoc(k) |
250 |
phiRef(2*k+2) = phiRef(2*k) |
251 |
& + ddPI*0.5*(tLoc(k)+tLoc(k+1)) |
252 |
ENDDO |
253 |
k = Nr |
254 |
ddPI=atm_Cp*( ((rC( k )/atm_Po)**atm_kappa) |
255 |
& -((rF(k+1)/atm_Po)**atm_kappa) ) |
256 |
phiRef(2*k+1) = phiRef(2*k) + ddPI*tLoc(k) |
257 |
C------ |
258 |
ENDIF |
259 |
|
260 |
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
261 |
ELSE |
262 |
STOP 'SET_REF_STATE: Bad value of buoyancyRelation !' |
263 |
C-- endif buoyancyRelation |
264 |
ENDIF |
265 |
|
266 |
C-- fill-in phiRef array (presently not used) |
267 |
IF ( buoyancyRelation.EQ.'OCEANIC' ) THEN |
268 |
c phiRef(1) = gravitySign*gravity*(rF(1)-Ro_SeaLevel) |
269 |
phiRef(1) = 0. _d 0 |
270 |
DO k=1,Nr |
271 |
phiRef(2*k) = gravitySign*gravity*(rC(k) - Ro_SeaLevel) |
272 |
phiRef(2*k+1) = gravitySign*gravity*(rF(k+1)-Ro_SeaLevel) |
273 |
ENDDO |
274 |
ELSEIF ( buoyancyRelation.EQ.'OCEANICP' ) THEN |
275 |
C should be : phiRef = phi_Origin - (rC - Ro_SeaLevel)/rhoConst |
276 |
C- but since the reference geopotential "phi_Origin" @ p = rF(k=1) |
277 |
C is not currently stored, we only get a relative geopotential: |
278 |
phiRef(1) = -recip_rhoConst*rF(1) |
279 |
DO k=1,Nr |
280 |
phiRef(2*k) = -recip_rhoConst*rC(k) |
281 |
phiRef(2*k+1) = -recip_rhoConst*rF(k+1) |
282 |
ENDDO |
283 |
ENDIF |
284 |
|
285 |
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
286 |
|
287 |
IF ( usingZCoords .AND. rhoRefFile .NE. ' ' ) THEN |
288 |
C-- anelastic formulation : set density factor from reference density profile |
289 |
C surface-interface rho-factor has to be 1: |
290 |
rhoFacF(1) = 1. _d 0 |
291 |
C rhoFac(k) = density ratio between layer k and top interface |
292 |
DO k=1,Nr |
293 |
rhoFacC(k) = rho1Ref(k)/rhoConst |
294 |
ENDDO |
295 |
DO k=2,Nr |
296 |
rhoFacF(k) = (rhoFacC(k-1)*drF(k)+rhoFacC(k)*drF(k-1)) |
297 |
& / (drF(k)+drF(k-1)) |
298 |
ENDDO |
299 |
C extrapolate down to the bottom: |
300 |
rhoFacF(Nr+1)= 2. _d 0*rhoFacC(Nr) - rhoFacF(Nr) |
301 |
C- set reciprocal rho-factor: |
302 |
DO k=1,Nr |
303 |
recip_rhoFacC(k) = 1. _d 0/rhoFacC(k) |
304 |
ENDDO |
305 |
DO k=1,Nr+1 |
306 |
recip_rhoFacF(k) = 1. _d 0/rhoFacF(k) |
307 |
ENDDO |
308 |
ENDIF |
309 |
|
310 |
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
311 |
|
312 |
C-- Write to check : |
313 |
IF (buoyancyRelation .EQ. 'ATMOSPHERIC') THEN |
314 |
WRITE(msgBuf,'(A)') ' ' |
315 |
CALL PRINT_MESSAGE( msgBuf, stdUnit, SQUEEZE_RIGHT, myThid ) |
316 |
WRITE(msgBuf,'(A)') |
317 |
& 'SET_REF_STATE: PhiRef/g [m] at level Center (integer)' |
318 |
CALL PRINT_MESSAGE( msgBuf, stdUnit, SQUEEZE_RIGHT, myThid ) |
319 |
WRITE(msgBuf,'(A)') |
320 |
& ' and at level Interface (half-int.) :' |
321 |
CALL PRINT_MESSAGE( msgBuf, stdUnit, SQUEEZE_RIGHT, myThid ) |
322 |
DO k=1,2*Nr+1 |
323 |
WRITE(msgBuf,'(A,F5.1,A,F15.1,A,F13.3)') |
324 |
& ' K=',k*0.5,' ; r=',rHalf(k),' ; phiRef/g=', |
325 |
& phiRef(k)*recip_gravity |
326 |
CALL PRINT_MESSAGE(msgBuf, stdUnit, SQUEEZE_RIGHT, myThid ) |
327 |
ENDDO |
328 |
ELSE |
329 |
C-- Write reference density to binary file : |
330 |
CALL WRITE_GLVEC_RL( 'RhoRef',' ',rhoRef, Nr, -1, myThid ) |
331 |
ENDIF |
332 |
|
333 |
C---+----1----+----2----+----3----+----4----+----5----+----6----+----7-|--+----| |
334 |
|
335 |
_END_MASTER( myThid ) |
336 |
_BARRIER |
337 |
|
338 |
RETURN |
339 |
END |