/[MITgcm]/MITgcm_contrib/atnguyen/code_21Dec2012_saltplume/salt_plume_volfrac.F
ViewVC logotype

Contents of /MITgcm_contrib/atnguyen/code_21Dec2012_saltplume/salt_plume_volfrac.F

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.7 - (show annotations) (download)
Fri May 2 06:10:47 2014 UTC (11 years, 7 months ago) by atn
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +38 -22 lines
reduce some global arrays to local

1 C $Header: /u/gcmpack/MITgcm_contrib/atnguyen/code_21Dec2012_saltplume/salt_plume_volfrac.F,v 1.6 2014/05/01 21:30:48 atn Exp $
2 C $Name: $
3
4 #include "SALT_PLUME_OPTIONS.h"
5
6 CBOP
7 C !ROUTINE: SALT_PLUME_VOLFRAC
8 C !INTERFACE:
9 SUBROUTINE SALT_PLUME_VOLFRAC(
10 I bi, bj, myTime, myIter, myThid )
11
12 C !DESCRIPTION: \bv
13 C *==========================================================*
14 C | SUBROUTINE SALT_PLUME_VOLFRAC
15 C | o Compute saltplume penetration.
16 C *==========================================================*
17 C | Compute fraction of volume flux associated with saltplume
18 C | flux penetrating through the entire water columns due to
19 C | rejected salt during freezing.
20 C |
21 C | For example, if surface value is Saltplume0,
22 C | and each level gets equal fraction 1/5 down to SPDepth=5,
23 C | SALT_PLUME_VOLFRAC will report
24 C | dSPvolkLev2Above[2to1,3to2,4to3,5to4,6to5] = [4/5,3/5,2/5,1/5, 0]
25 C | dSPvolSurf2kLev [1to1,1to2,1to3,1to4,1to5] = [1/5,1/5,1/5,1/5,1/5]
26 C | sum [into5] = 1to5 + 6to5 - 5to4 = 1/5 + 0 - 1/5 = 0
27 C | [into4] = 1to4 + 5to4 - 4to3 = 1/5 + 1/5 - 2/5 = 0
28 C | [into3] = 1to3 + 4to3 - 3to2 = 1/5 + 2/5 - 3/5 = 0
29 C | [into2] = 1to2 + 3to2 - 2to1 = 1/5 + 3/5 - 4/5 = 0
30 C | [into1] = 1to1 + 2to1 - 1to[1,2,3,4,5] = 1/5 + 4/5 - 5/5 = 0
31 C | NOTE: volume will always be conserved.
32 C | =====
33 C | Written by : ATN (based on SALT_PLUME_FRAC)
34 C | Date : Apr 14, 2014
35 C *==========================================================*
36 C \ev
37
38 C !USES:
39 IMPLICIT NONE
40 #include "SIZE.h"
41 #include "GRID.h"
42 #include "SALT_PLUME.h"
43 #include "EEPARAMS.h"
44 #include "PARAMS.h"
45
46 C !INPUT/OUTPUT PARAMETERS:
47 C input arguments
48 C SPDpeth :: corresponding SaltPlumeDepth(i,j) at this grid point
49 C myTime :: Current time in simulation
50 C myIter :: Current iteration number in simulation
51 C myThid :: My Thread Id. number
52 INTEGER bi,bj
53 _RL myTime
54 INTEGER myIter
55 INTEGER myThid
56 C input/output arguments
57 C CHARACTER*(MAX_LEN_MBUF) msgBuf
58 CEOP
59
60 #ifdef ALLOW_SALT_PLUME
61 #ifdef SALT_PLUME_VOLUME
62
63 C !LOCAL VARIABLES:
64 _RL dMbdt (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
65 C _RL dVbdt (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
66 _RL SPkBottom (1-OLx:sNx+OLx,1-OLy:sNy+OLy)
67 _RL SPplumek (1-OLx:sNx+OLx,1-OLy:sNy+OLy,Nr+1)
68 _RL dplumek
69 _RL locz, zo, z20
70 INTEGER i,j,k,kp1,kk,Nlev,Nrp1
71 _RL three, S, So
72 parameter( three = 3. _d 0 )
73 C This is an abbreviation of 1./(exp(1.)-1.)
74 _RL recip_expOneM1
75 parameter( recip_expOneM1 = 0.581976706869326343 )
76
77 C initialize at every time step
78 Nrp1=Nr+1
79 dplumek = 0. _d 0
80 DO k=1,Nr
81 DO j=1-OLy,sNy+OLy
82 DO i=1-OLx,sNx+OLx
83 dSPvolSurf2kLev(i,j,k,bi,bj) = 0. _d 0
84 C dSPvolBelow2kLev(i,j,k,bi,bj) = 0. _d 0
85 dSPvolkLev2Above(i,j,k,bi,bj) = 0. _d 0
86 C SPplumek(i,j,k,bi,bj) = 1. _d 0
87 SPplumek(i,j,k) = 1. _d 0
88 ENDDO
89 ENDDO
90 ENDDO
91 DO j=1-OLy,sNy+OLy
92 DO i=1-OLx,sNx+OLx
93 C dSPvolBelow2kLev(i,j,Nrp1,bi,bj) = 0. _d 0
94 C SPplumek(i,j,Nrp1,bi,bj) = 1. _d 0
95 SPplumek(i,j,Nrp1) = 1. _d 0
96 C
97 C SPbrineSalt(i,j,bi,bj) = 0. _d 0
98 SPbrineVolFlux(i,j,bi,bj) = 0. _d 0
99 C dVbdt(i,j) = 0. _d 0
100 dMbdt(i,j) = 0. _d 0
101 SPkBottom(i,j) = 0
102 ENDDO
103 ENDDO
104
105 DO k = 1,Nr+1
106 DO j=1-OLy,sNy+OLy
107 DO i=1-OLx,sNx+OLx
108 locz = abs(rF(k))
109
110 IF ( SaltPlumeDepth(i,j,bi,bj).GT.locz .and.
111 & SaltPlumeDepth(i,j,bi,bj).GT.zeroRL ) THEN
112
113 SPkBottom(i,j)=min(k,Nr)
114 C Default: uniform distribution, PlumeMethod=1, Npower=0
115 IF (PlumeMethod .EQ. 1) THEN
116 zo = abs(SaltPlumeDepth(i,j,bi,bj))
117 S = oneRL !input depth temp
118 So = oneRL
119 DO kk=1,Npower+1
120 S = locz*S !raise to the Npower+1
121 So = zo*So
122 ENDDO
123 C SPplumek(i,j,k,bi,bj) = max(zeroRL,S/So)
124 SPplumek(i,j,k) = max(zeroRL,S/So)
125
126 ELSEIF (PlumeMethod .EQ. 2) THEN !exponential distribution
127 z20 = abs(SaltPlumeDepth(i,j,bi,bj))
128 S = exp(locz/z20)-oneRL
129 So = recip_expOneM1 !So = exp(one)-one
130 C SPplumek(i,j,k,bi,bj) = max(zeroRL,S*So)
131 SPplumek(i,j,k) = max(zeroRL,S*So)
132
133 C PlumeMethod = 3, distribute salt LINEARLY between SPDepth and
134 C SPDepth/SPovershoot
135 C (1-SPovershoot)percent has already been taken into account in
136 C SPDepth calculation, i.e., SPDepth = SPovershoot*SPDepth.
137 ELSEIF (PlumeMethod .EQ. 3) THEN !overshoot 20%
138 z20 = abs(SaltPlumeDepth(i,j,bi,bj))
139 zo = z20/SPovershoot
140 So = z20-zo
141 S = locz-zo
142 IF( (locz.GE.zo).AND.(locz.LT.z20) ) THEN
143 C SPplumek(i,j,k,bi,bj) = max(zeroRL,S/So)
144 SPplumek(i,j,k) = max(zeroRL,S/So)
145 ELSE
146 C SPplumek(i,j,k,bi,bj) = zeroRL
147 SPplumek(i,j,k) = max(zeroRL,S/So)
148 ENDIF
149
150 C PlumeMethod = 5, dumping all salt at the top layer
151 ELSEIF (PlumeMethod .EQ. 5) THEN
152 z20 = oneRL
153 zo = zeroRL
154 IF( (locz.GE.zo).AND.(locz.LT.z20) ) THEN
155 C SPplumek(i,j,k,bi,bj) = zeroRL
156 SPplumek(i,j,k) = zeroRL
157 ELSE
158 C SPplumek(i,j,k,bi,bj) = oneRL
159 SPplumek(i,j,k) = oneRL
160 ENDIF
161 ELSEIF (PlumeMethod .EQ. 6) THEN
162 C PLumeMethod = 6, currently only works for Npower = 1 and 2.
163 z20 = abs(SaltPlumeDepth(i,j,bi,bj))
164 S = oneRL !input depth temp
165 So = oneRL
166 DO kk=1,Npower+1
167 S = locz*S !raise to the Npower+1
168 So = z20*So
169 ENDDO
170 IF(Npower.EQ.1) THEN !Npower=1
171 C SPplumek(i,j,k,bi,bj) = max(zeroRL,twoRL/z20*locz-S/So)
172 SPplumek(i,j,k) = max(zeroRL,twoRL/z20*locz-S/So)
173 ELSE !Npower=2
174 C SPplumek(i,j,k,bi,bj) = max(zeroRL,
175 SPplumek(i,j,k) = max(zeroRL,
176 & three/z20*locz - three/(z20*z20)*locz*locz + S/So)
177 ENDIF
178
179 ELSEIF (PlumeMethod .EQ. 7) THEN
180 C PLumeMethod = 7, dump an offset parabolla with more salt at surface
181 C tapered to zero at depth SPDepth/2, then increased until SPDepth
182 C need input SPDepth, NPower = percentage of SPDepth
183 C Ex: if Npower = 10 -> (10/2)=5% of SPDepth
184 C NPower can be negative integer here.
185 C 0 -> parabola centered at SPDepth/2;
186 C + -> parabola offset, salt @ surface < @ SPDepth
187 C - -> parabola offset, salt @ surface > @ SPDepth
188 C S and So are dummy variables
189 z20 = abs(SaltPlumeDepth(i,j,bi,bj))
190 zo = z20*(oneRL/twoRL-Npower/200. _d 0)
191 So = (z20*z20*z20/three)
192 & - (z20*z20)*zo
193 & + (z20) *zo*zo
194 S = (locz*locz*locz/three)
195 & - (locz*locz)*zo
196 & + (locz) *zo*zo
197 C SPplumek(i,j,k,bi,bj) = max(zeroRL,(S/So))
198 SPplumek(i,j,k) = max(zeroRL,(S/So))
199
200 ELSE
201 WRITE(*,*) 'salt_plume_frac: PLumeMethod =', PLumeMethod,
202 & 'not implemented'
203 STOP 'ABNORMAL in S/R SALT_PLUME_FRAC'
204 ENDIF
205 ELSE
206 C SPplumek(i,j,k,bi,bj) = oneRL
207 SPplumek(i,j,k) = oneRL
208 ENDIF
209 ENDDO
210 ENDDO
211 ENDDO
212
213 C Now calculating dplumek, dSPvolumeUp, dSPvolSurf2kLev
214 C units:
215 C Sbrine=dsb/dt*dt/(rhoConst*SPalpha*drF)[psu kg/m2/s*s/(kg/m3*m)]=[psu]
216 C SPplumek : fraction : unitless
217 C SaltPlumeFlux: dsb/dt [psu.kg/m^2/s = g/m^2/s]
218 C brine_mass_flux dMb/dt = dsb/dt / Sbrine [kg/m2/s]
219 C = dsb/dt / (dsb/dt*dt/(rhoConst*SPalpha*drF))
220 C = rhoConst*SPalpha*drF/dt [kg/m3 m/s]=[kg/m2/s]
221 C dVbrine/dt = dMb/dt 1/rhoConst [m/s]
222
223 C has 2 ways to define brine properties: either provide
224 C (A) SPalpha: vol frac or (B) SPbrineSalt: brine salinity.
225 C (A) SPalpha: can calc SPbrineSalt as fxn of dhice/dt,
226 C constrained by SPbrineSaltmax:
227 C SPbrineSalt=SaltPlumeFlux/rhoConst/SPalpha/drF(1)*dt
228 C SPbrineSalt=min(SPbrineSalt,SPbrineSaltmax)
229 C dMbdt = saltPlumeFlux / SPbrineSalt
230 C = rhoConst*SPalpha*drF(1)/dt <-- a function of SPalpha
231 C (B) SPbrinesalt provided
232 C dMbdt = saltPlumeFlux / SPbrineSalt <-- fxn of SPbrineSalt
233
234 C Assuming we go with (B) here:
235 DO j=1-OLy,sNy+OLy
236 DO i=1-OLx,sNx+OLx
237 C brine salinity at surface:
238 C SPbrineSalt(i,j,bi,bj)= saltPlumeFlux(i,j,bi,bj)/SPalpha
239 C & *mass2rUnit*recip_drF(1)*dTtracerLev(1)
240 C SPbrineSalt(i,j,bi,bj) = SPbrineSconst
241 C SPbrineSalt(i,j,bi,bj) = min( SPbrineSalt(i,j,bi,bj)
242 C & ,SPbrineSaltmax )
243 C brine mass and volume at surface:
244 dMbdt(i,j)=saltPlumeFlux(i,j,bi,bj)/SPbrineSconst
245 C dVbdt(i,j)=dMbdt(i,j)*mass2rUnit
246 SPbrineVolFlux(i,j,bi,bj)=dMbdt(i,j)*mass2rUnit
247 ENDDO
248 ENDDO
249
250 C Distributing down: this is always from level 1 to depth
251 DO k=Nr,1,-1
252 DO j=1-OLy,sNy+OLy
253 DO i=1-OLx,sNx+OLx
254 C dplumek=SPplumek(i,j,k+1,bi,bj)-SPplumek(i,j,k,bi,bj)
255 dplumek=SPplumek(i,j,k+1)-SPplumek(i,j,k)
256 C dSPvolSurf2kLev(i,j,k,bi,bj)=dplumek*dVbdt(i,j)
257 dSPvolSurf2kLev(i,j,k,bi,bj)=dplumek*SPbrineVolFlux(i,j,bi,bj)
258 ENDDO
259 ENDDO
260 ENDDO
261
262 C Now volume up: need to scan from bottom of SPDepth
263 DO j=1-OLy,sNy+OLy
264 DO i=1-OLx,sNx+OLx
265 Nlev=SPkBottom(i,j)
266 IF(Nlev.GE.1 .AND. Nlev.LE.Nr) THEN
267 DO k=Nlev,1,-1
268 kp1=k+1
269 C dSPvolBelow2kLev(i,j,k,bi,bj)=-dSPvolkLev2Above(i,j,k+1,bi,bj)
270 C dSPvolkLev2Above(i,j,k,bi,bj)=-(dSPvolBelow2kLev(i,j,k,bi,bj)
271 C & + dSPvolSurf2kLev(i,j,k,bi,bj))
272 dSPvolkLev2Above(i,j,k,bi,bj)=dSPvolkLev2Above(i,j,kp1,bi,bj)
273 & - dSPvolSurf2kLev(i,j,k,bi,bj)
274 ENDDO
275 ENDIF
276 ENDDO
277 ENDDO
278
279 #ifdef ALLOW_DIAGNOSTICS
280 IF ( useDiagnostics ) THEN
281 C CALL DIAGNOSTICS_FILL(
282 C & SPkBottom,'SPkbottm',0,1,1,bi,bj,myThid )
283 C CALL DIAGNOSTICS_FILL(
284 C & SPbrineSalt,'SPbrineS',0,1,1,bi,bj,myThid )
285 CALL DIAGNOSTICS_FILL(
286 & SPplumek,'PLUMEKB ',0,Nr,2,bi,bj,myThid )
287 C CALL DIAGNOSTICS_FILL(
288 C & SPplumek,'PLUMEKB ',0,Nr,1,bi,bj,myThid )
289 C CALL DIAGNOSTICS_FILL(
290 C & dSPvolSurf2kLev,'SPVs2k ',0,Nr,1,bi,bj,myThid )
291 C CALL DIAGNOSTICS_FILL(
292 C & dSPvolBelow2kLev,'SPVp2k ',0,Nr,1,bi,bj,myThid )
293 C CALL DIAGNOSTICS_FILL(
294 C & dSPvolkLev2Above,'SPVk2m ',0,Nr,1,bi,bj,myThid )
295 ENDIF
296 #endif /* ALLOW_DIAGNOSTICS */
297
298 #endif /* SALT_PLUME_VOLUME */
299 #endif /* ALLOW_SALT_PLUME */
300
301 RETURN
302 END

  ViewVC Help
Powered by ViewVC 1.1.22