1 | MODULE sbcclo |
---|
2 | !!====================================================================== |
---|
3 | !! *** MODULE sbcclo *** |
---|
4 | !! Ocean forcing: closea sea correction |
---|
5 | !!===================================================================== |
---|
6 | !! History : 4.1 ! 2019-09 (P. Mathiot) original |
---|
7 | !! NEMO |
---|
8 | !!---------------------------------------------------------------------- |
---|
9 | ! |
---|
10 | !!---------------------------------------------------------------------- |
---|
11 | !! sbc_clo : update emp and qns over target area and source area |
---|
12 | !! sbc_clo_init : initialise all variable needed for closed sea correction |
---|
13 | !! |
---|
14 | !! alloc_cssurf : allocate closed sea surface array |
---|
15 | !! alloc_csgrp : allocate closed sea group array |
---|
16 | !! get_cssrcsurf : compute source surface area |
---|
17 | !! get_cstrgsurf : compute target surface area |
---|
18 | !! prt_csctl : closed sea control print |
---|
19 | !! sbc_csupdate : compute net fw from closed sea |
---|
20 | !!---------------------------------------------------------------------- |
---|
21 | ! |
---|
22 | USE oce ! dynamics and tracers |
---|
23 | USE dom_oce ! ocean space and time domain |
---|
24 | USE closea ! closed sea |
---|
25 | USE phycst ! physical constants |
---|
26 | USE sbc_oce ! ocean surface boundary conditions |
---|
27 | USE iom ! I/O routines |
---|
28 | ! |
---|
29 | USE in_out_manager ! I/O manager |
---|
30 | USE lib_fortran, ONLY: glob_sum |
---|
31 | USE lib_mpp ! MPP library |
---|
32 | ! |
---|
33 | IMPLICIT NONE |
---|
34 | ! |
---|
35 | PRIVATE alloc_cssurf |
---|
36 | PRIVATE alloc_csgrp |
---|
37 | PRIVATE get_cssrcsurf |
---|
38 | PRIVATE get_cstrgsurf |
---|
39 | PRIVATE prt_csctl |
---|
40 | PRIVATE sbc_csupdate |
---|
41 | ! |
---|
42 | PUBLIC sbc_clo |
---|
43 | PUBLIC sbc_clo_init |
---|
44 | ! |
---|
45 | REAL(wp), PUBLIC, SAVE, ALLOCATABLE, DIMENSION(:) :: rsurfsrcg, rsurftrgg !: closed sea target glo surface areas |
---|
46 | REAL(wp), PUBLIC, SAVE, ALLOCATABLE, DIMENSION(:) :: rsurfsrcr, rsurftrgr !: closed sea target rnf surface areas |
---|
47 | REAL(wp), PUBLIC, SAVE, ALLOCATABLE, DIMENSION(:) :: rsurfsrce, rsurftrge !: closed sea target emp surface areas |
---|
48 | ! |
---|
49 | INTEGER, PUBLIC, SAVE, ALLOCATABLE, DIMENSION(:) :: mcsgrpg, mcsgrpr, mcsgrpe !: closed sea group for glo, rnf and emp |
---|
50 | ! |
---|
51 | CONTAINS |
---|
52 | ! |
---|
53 | !!---------------------------------------------------------------------- |
---|
54 | !! Public subroutines |
---|
55 | !!---------------------------------------------------------------------- |
---|
56 | ! |
---|
57 | SUBROUTINE sbc_clo_init |
---|
58 | !!--------------------------------------------------------------------- |
---|
59 | !! *** ROUTINE sbc_clo_init *** |
---|
60 | !! |
---|
61 | !! ** Purpose : Initialisation of the net fw closed sea correction |
---|
62 | !! |
---|
63 | !! ** Method : - compute source surface area for each closed sea |
---|
64 | !! - defined the group of each closed sea |
---|
65 | !! (needed to manage multiple closed sea and one target area like great lakes / St Laurent outlet) |
---|
66 | !! - compute target surface area and corresponding group for each closed sea |
---|
67 | !!---------------------------------------------------------------------- |
---|
68 | ! |
---|
69 | ! 0. Allocate cs variables (surf) |
---|
70 | CALL alloc_cssurf( ncsg, rsurfsrcg, rsurftrgg ) |
---|
71 | CALL alloc_cssurf( ncsr, rsurfsrcr, rsurftrgr ) |
---|
72 | CALL alloc_cssurf( ncse, rsurfsrce, rsurftrge ) |
---|
73 | ! |
---|
74 | ! 1. compute source surface area |
---|
75 | CALL get_cssrcsurf( ncsg, mask_csglo, rsurfsrcg ) |
---|
76 | CALL get_cssrcsurf( ncsr, mask_csrnf, rsurfsrcr ) |
---|
77 | CALL get_cssrcsurf( ncse, mask_csemp, rsurfsrce ) |
---|
78 | ! |
---|
79 | ! 2. Allocate cs group variables (mcsgrp) |
---|
80 | CALL alloc_csgrp( ncsg, mcsgrpg ) |
---|
81 | CALL alloc_csgrp( ncsr, mcsgrpr ) |
---|
82 | CALL alloc_csgrp( ncse, mcsgrpe ) |
---|
83 | ! |
---|
84 | ! 3. compute target surface area and group number (mcsgrp) for all cs and cases |
---|
85 | ! glo could be simpler but for lisibility, all treated the same way |
---|
86 | ! It is only done once, so not a big deal |
---|
87 | CALL get_cstrgsurf( ncsg, mask_csglo, mask_csgrpglo, rsurftrgg, mcsgrpg ) |
---|
88 | CALL get_cstrgsurf( ncsr, mask_csrnf, mask_csgrprnf, rsurftrgr, mcsgrpr ) |
---|
89 | CALL get_cstrgsurf( ncse, mask_csemp, mask_csgrpemp, rsurftrge, mcsgrpe ) |
---|
90 | ! |
---|
91 | ! 4. print out in ocean.ouput |
---|
92 | CALL prt_csctl( ncsg, rsurfsrcg, rsurftrgg, mcsgrpg, 'glo' ) |
---|
93 | CALL prt_csctl( ncsr, rsurfsrcr, rsurftrgr, mcsgrpr, 'rnf' ) |
---|
94 | CALL prt_csctl( ncse, rsurfsrce, rsurftrge, mcsgrpe, 'emp' ) |
---|
95 | |
---|
96 | END SUBROUTINE sbc_clo_init |
---|
97 | |
---|
98 | SUBROUTINE sbc_clo( kt ) ! to be move in SBC in a file sbcclo ??? |
---|
99 | !!--------------------------------------------------------------------- |
---|
100 | !! *** ROUTINE sbc_clo *** |
---|
101 | !! |
---|
102 | !! ** Purpose : Special handling of closed seas |
---|
103 | !! |
---|
104 | !! ** Method : Water flux is forced to zero over closed sea |
---|
105 | !! Excess is shared between remaining ocean, or |
---|
106 | !! put as run-off in open ocean. |
---|
107 | !! |
---|
108 | !! ** Action : - compute surface freshwater fluxes and associated heat content flux at kt |
---|
109 | !! - output closed sea contribution to fw and heat budget |
---|
110 | !! - update emp and qns |
---|
111 | !!---------------------------------------------------------------------- |
---|
112 | INTEGER , INTENT(in ) :: kt ! ocean model time step |
---|
113 | ! |
---|
114 | REAL(wp), DIMENSION(jpi,jpj) :: zwcs, zqcs ! water flux and heat flux correction due to closed seas |
---|
115 | !!---------------------------------------------------------------------- |
---|
116 | ! |
---|
117 | ! 0. initialisation |
---|
118 | zwcs(:,:) = 0._wp ; zqcs(:,:) = 0._wp |
---|
119 | ! |
---|
120 | ! 1. update emp and qns |
---|
121 | CALL sbc_csupdate( ncsg, mcsgrpg, mask_csglo, mask_csgrpglo, rsurfsrcg, rsurftrgg, 'glo', mask_opnsea, rsurftrgg, zwcs, zqcs ) |
---|
122 | CALL sbc_csupdate( ncsr, mcsgrpr, mask_csrnf, mask_csgrprnf, rsurfsrcr, rsurftrgr, 'rnf', mask_opnsea, rsurftrgg, zwcs, zqcs ) |
---|
123 | CALL sbc_csupdate( ncse, mcsgrpe, mask_csemp, mask_csgrpemp, rsurfsrce, rsurftrge, 'emp', mask_opnsea, rsurftrgg, zwcs, zqcs ) |
---|
124 | ! |
---|
125 | ! 2. ouput closed sea contributions |
---|
126 | CALL iom_put('wclosea',zwcs) |
---|
127 | CALL iom_put('qclosea',zqcs) |
---|
128 | ! |
---|
129 | ! 3. update emp and qns |
---|
130 | emp(:,:) = emp(:,:) + zwcs(:,:) |
---|
131 | qns(:,:) = qns(:,:) + zqcs(:,:) |
---|
132 | ! |
---|
133 | END SUBROUTINE sbc_clo |
---|
134 | ! |
---|
135 | !!---------------------------------------------------------------------- |
---|
136 | !! Private subroutines |
---|
137 | !!---------------------------------------------------------------------- |
---|
138 | ! |
---|
139 | SUBROUTINE get_cssrcsurf(kncs, kmaskcs, psurfsrc) |
---|
140 | !!----------------------------------------------------------------------- |
---|
141 | !! *** routine get_cssrcsurf *** |
---|
142 | !! |
---|
143 | !! ** Purpose : compute closed sea (source) surface area |
---|
144 | !!---------------------------------------------------------------------- |
---|
145 | ! subroutine parameters |
---|
146 | INTEGER, INTENT(in ) :: kncs ! closed sea number |
---|
147 | INTEGER, DIMENSION(:,:), INTENT(in ) :: kmaskcs ! closed sea mask |
---|
148 | |
---|
149 | REAL(wp), DIMENSION(:) , INTENT(inout) :: psurfsrc ! source surface area |
---|
150 | |
---|
151 | ! local variables |
---|
152 | INTEGER :: jcs ! loop index |
---|
153 | INTEGER, DIMENSION(jpi,jpj) :: imsksrc ! source mask |
---|
154 | !!---------------------------------------------------------------------- |
---|
155 | ! |
---|
156 | DO jcs = 1,kncs ! loop over closed seas |
---|
157 | ! |
---|
158 | ! 0. build river mouth mask for this lake |
---|
159 | WHERE ( kmaskcs == jcs ) |
---|
160 | imsksrc = 1 |
---|
161 | ELSE WHERE |
---|
162 | imsksrc = 0 |
---|
163 | END WHERE |
---|
164 | ! |
---|
165 | ! 1. compute target area |
---|
166 | psurfsrc(jcs) = glob_sum('closea', e1e2t(:,:) * imsksrc(:,:) ) |
---|
167 | ! |
---|
168 | END DO ! jcs |
---|
169 | |
---|
170 | END SUBROUTINE |
---|
171 | |
---|
172 | SUBROUTINE get_cstrgsurf(kncs, kmaskcs, kmaskcsgrp, psurftrg, kcsgrp ) |
---|
173 | !!----------------------------------------------------------------------- |
---|
174 | !! *** routine get_cstrgsurf *** |
---|
175 | !! |
---|
176 | !! ** Purpose : compute closed sea (target) surface area |
---|
177 | !!---------------------------------------------------------------------- |
---|
178 | ! subroutine parameters |
---|
179 | INTEGER, INTENT(in ) :: kncs ! closed sea number |
---|
180 | INTEGER, DIMENSION(:) , INTENT(inout) :: kcsgrp ! closed sea group number |
---|
181 | INTEGER, DIMENSION(:,:), INTENT(in ) :: kmaskcs, kmaskcsgrp ! closed sea and group mask |
---|
182 | |
---|
183 | REAL(wp), DIMENSION(:) , INTENT(inout) :: psurftrg ! target surface area |
---|
184 | |
---|
185 | ! local variables |
---|
186 | INTEGER :: jcs, jtmp ! tmp |
---|
187 | INTEGER, DIMENSION(jpi,jpj) :: imskgrp, imsksrc, imsktrg ! tmp group, source and target mask |
---|
188 | !!---------------------------------------------------------------------- |
---|
189 | ! |
---|
190 | DO jcs = 1,kncs ! loop over closed seas |
---|
191 | ! |
---|
192 | !! 0. find group number for cs number jcs |
---|
193 | imskgrp = kmaskcsgrp |
---|
194 | imsksrc = kmaskcs |
---|
195 | ! |
---|
196 | ! set cs value where cs is |
---|
197 | imsktrg = HUGE(1) |
---|
198 | WHERE ( imsksrc == jcs ) imsktrg = jcs |
---|
199 | ! |
---|
200 | ! zmsk = HUGE outside the cs number jcs |
---|
201 | ! ktmp = jcs - group number |
---|
202 | ! jgrp = group corresponding to the cs jcs |
---|
203 | imsktrg = imsktrg - imskgrp |
---|
204 | jtmp = MINVAL(imsktrg) ; CALL mpp_min('closea',jtmp) |
---|
205 | kcsgrp(jcs) = jcs - jtmp |
---|
206 | ! |
---|
207 | !! 1. build river mouth mask for this lake |
---|
208 | WHERE ( imskgrp * mask_opnsea == kcsgrp(jcs) ) |
---|
209 | imsktrg = 1 |
---|
210 | ELSE WHERE |
---|
211 | imsktrg = 0 |
---|
212 | END WHERE |
---|
213 | ! |
---|
214 | !! 2. compute target area |
---|
215 | psurftrg(jcs) = glob_sum('closea', e1e2t(:,:) * imsktrg(:,:) ) |
---|
216 | ! |
---|
217 | END DO ! jcs |
---|
218 | |
---|
219 | END SUBROUTINE |
---|
220 | |
---|
221 | SUBROUTINE prt_csctl(kncs, psurfsrc, psurftrg, kcsgrp, cdcstype) |
---|
222 | !!----------------------------------------------------------------------- |
---|
223 | !! *** routine prt_csctl *** |
---|
224 | !! |
---|
225 | !! ** Purpose : output information about each closed sea (src id, trg id, src area and trg area) |
---|
226 | !!---------------------------------------------------------------------- |
---|
227 | ! subroutine parameters |
---|
228 | INTEGER, INTENT(in ) :: kncs ! closed sea number |
---|
229 | INTEGER, DIMENSION(:), INTENT(in ) :: kcsgrp ! closed sea group number |
---|
230 | ! |
---|
231 | REAL(wp), DIMENSION(:), INTENT(in ) :: psurfsrc, psurftrg ! source and target surface area |
---|
232 | ! |
---|
233 | CHARACTER(256), INTENT(in ) :: cdcstype ! closed sea scheme used for redistribution |
---|
234 | ! |
---|
235 | ! local variable |
---|
236 | INTEGER :: jcs |
---|
237 | !!---------------------------------------------------------------------- |
---|
238 | ! |
---|
239 | IF ( lwp .AND. kncs > 0 ) THEN |
---|
240 | WRITE(numout,*)'' |
---|
241 | ! |
---|
242 | WRITE(numout,*)'Closed sea target ',TRIM(cdcstype),' : ' |
---|
243 | ! |
---|
244 | DO jcs = 1,kncs |
---|
245 | WRITE(numout,FMT='(3a,i3,a,i3)') ' ',TRIM(cdcstype),' closed sea id is ',jcs,' and trg id is : ', kcsgrp(jcs) |
---|
246 | WRITE(numout,FMT='(a,f12.2)' ) ' src surface areas (km2) : ', psurfsrc(jcs) * 1.0e-6 |
---|
247 | WRITE(numout,FMT='(a,f12.2)' ) ' trg surface areas (km2) : ', psurftrg(jcs) * 1.0e-6 |
---|
248 | END DO |
---|
249 | ! |
---|
250 | WRITE(numout,*)'' |
---|
251 | END IF |
---|
252 | |
---|
253 | END SUBROUTINE |
---|
254 | |
---|
255 | SUBROUTINE sbc_csupdate(kncs, kcsgrp, kmsk_src, kmsk_trg, psurfsrc, psurftrg, cdcstype, kmsk_opnsea, psurf_opnsea, pwcs, pqcs) |
---|
256 | !!----------------------------------------------------------------------- |
---|
257 | !! *** routine sbc_csupdate *** |
---|
258 | !! |
---|
259 | !! ** Purpose : - compute the net freshwater fluxes over each closed seas |
---|
260 | !! - apply correction to closed sea source/target net fwf accordingly |
---|
261 | !!---------------------------------------------------------------------- |
---|
262 | ! subroutine parameters |
---|
263 | INTEGER, INTENT(in) :: kncs ! closed sea number |
---|
264 | INTEGER, DIMENSION(: ), INTENT(in) :: kcsgrp ! closed sea group number |
---|
265 | INTEGER, DIMENSION(:,:), INTENT(in) :: kmsk_src, kmsk_trg, kmsk_opnsea ! source, target, open ocean mask |
---|
266 | |
---|
267 | REAL(wp), DIMENSION(:) , INTENT(in ) :: psurfsrc, psurftrg, psurf_opnsea ! source, target and open ocean surface area |
---|
268 | REAL(wp), DIMENSION(:,:), INTENT(inout) :: pwcs, pqcs ! water and heat flux correction due to closed seas |
---|
269 | |
---|
270 | CHARACTER(256), INTENT(in ) :: cdcstype ! closed sea scheme used for redistribution |
---|
271 | |
---|
272 | ! local variables |
---|
273 | INTEGER :: jcs ! loop index over closed sea |
---|
274 | INTEGER, DIMENSION(jpi,jpj) :: imsk_src, imsk_trg ! tmp array source and target closed sea masks |
---|
275 | |
---|
276 | REAL(wp) :: zcoef, zcoef1, ztmp ! tmp |
---|
277 | REAL(wp) :: zcsfwf ! tmp net fwf over one closed sea |
---|
278 | REAL(wp) :: zsurftrg ! tmp target surface area |
---|
279 | !!---------------------------------------------------------------------- |
---|
280 | ! |
---|
281 | DO jcs = 1, kncs ! loop over closed seas |
---|
282 | ! |
---|
283 | !! 0. get mask of each closed sea |
---|
284 | imsk_src(:,:) = 0 |
---|
285 | WHERE ( kmsk_src(:,:) == jcs ) imsk_src(:,:) = 1 |
---|
286 | ! |
---|
287 | !! 1. Work out net freshwater fluxes over each closed seas from EMP - RNF. |
---|
288 | zcsfwf = glob_sum( 'closea', e1e2t(:,:) * ( emp(:,:)-rnf(:,:) ) * imsk_src(:,:) ) |
---|
289 | ! |
---|
290 | !! 2. Deal with runoff special case (net evaporation spread globally) |
---|
291 | IF (cdcstype == 'rnf' .AND. zcsfwf > 0) THEN |
---|
292 | zsurftrg = psurf_opnsea(1) |
---|
293 | imsk_trg = kmsk_opnsea * kcsgrp(jcs) ! set imsk_trg value to the corresponding group id |
---|
294 | ELSE |
---|
295 | zsurftrg = psurftrg(jcs) |
---|
296 | imsk_trg = kmsk_trg |
---|
297 | END IF |
---|
298 | imsk_trg = imsk_trg * kmsk_opnsea |
---|
299 | ! |
---|
300 | !! 3. Add residuals to target points |
---|
301 | zcoef = zcsfwf / zsurftrg |
---|
302 | zcoef1 = rcp * zcoef |
---|
303 | WHERE( imsk_trg(:,:) == kcsgrp(jcs) ) |
---|
304 | pwcs(:,:) = pwcs(:,:) + zcoef |
---|
305 | pqcs(:,:) = pqcs(:,:) - zcoef1 * sst_m(:,:) |
---|
306 | ENDWHERE |
---|
307 | ! |
---|
308 | !! 4. Subtract residuals from source points |
---|
309 | zcoef = zcsfwf / psurfsrc(jcs) |
---|
310 | zcoef1 = rcp * zcoef |
---|
311 | WHERE( kmsk_src(:,:) == jcs ) |
---|
312 | pwcs(:,:) = pwcs(:,:) - zcoef |
---|
313 | pqcs(:,:) = pqcs(:,:) + zcoef1 * sst_m(:,:) |
---|
314 | ENDWHERE |
---|
315 | ! |
---|
316 | END DO ! jcs |
---|
317 | |
---|
318 | END SUBROUTINE |
---|
319 | |
---|
320 | SUBROUTINE alloc_cssurf( klen, pvarsrc, pvartrg ) |
---|
321 | !!----------------------------------------------------------------------- |
---|
322 | !! *** routine alloc_cssurf *** |
---|
323 | !! |
---|
324 | !! ** Purpose : allocate closed sea surface array (source) |
---|
325 | !!---------------------------------------------------------------------- |
---|
326 | ! subroutine parameters |
---|
327 | INTEGER, INTENT(in) :: klen |
---|
328 | REAL(wp), ALLOCATABLE, DIMENSION(:), INTENT(inout) :: pvarsrc, pvartrg |
---|
329 | ! |
---|
330 | ! local variables |
---|
331 | INTEGER :: ierr |
---|
332 | !!---------------------------------------------------------------------- |
---|
333 | ! |
---|
334 | ! klen (number of lake) can be zero so use MAX(klen,1) to avoid 0 length array |
---|
335 | ALLOCATE( pvarsrc(MAX(klen,1)) , pvartrg(MAX(klen,1)) , STAT=ierr ) |
---|
336 | IF( ierr /= 0 ) CALL ctl_stop( 'STOP', 'sbc_clo: failed to allocate surf array') |
---|
337 | ! |
---|
338 | ! initialise to 0 |
---|
339 | pvarsrc(:) = 0.e0_wp |
---|
340 | pvartrg(:) = 0.e0_wp |
---|
341 | END SUBROUTINE |
---|
342 | |
---|
343 | SUBROUTINE alloc_csgrp( klen, kvar ) |
---|
344 | !!----------------------------------------------------------------------- |
---|
345 | !! *** routine alloc_csgrp *** |
---|
346 | !! |
---|
347 | !! ** Purpose : allocate closed sea group surface array |
---|
348 | !!---------------------------------------------------------------------- |
---|
349 | ! subroutine parameters |
---|
350 | INTEGER, INTENT(in) :: klen |
---|
351 | INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(inout) :: kvar |
---|
352 | ! |
---|
353 | ! local variables |
---|
354 | INTEGER :: ierr |
---|
355 | !!---------------------------------------------------------------------- |
---|
356 | ! |
---|
357 | ! klen (number of lake) can be zero so use MAX(klen,1) to avoid 0 length array |
---|
358 | ALLOCATE( kvar(MAX(klen,1)) , STAT=ierr ) |
---|
359 | IF( ierr /= 0 ) CALL ctl_stop( 'STOP', 'sbc_clo: failed to allocate group array') |
---|
360 | ! initialise to 0 |
---|
361 | kvar(:) = 0 |
---|
362 | END SUBROUTINE |
---|
363 | |
---|
364 | END MODULE |
---|