SURFEX  V8_0
Surfex V8_0 release
 All Classes Files Functions Variables
modi_glt_vhdslab_r.F90
Go to the documentation of this file.
1 !SFX_LIC Copyright 1994-2014 CNRS, Meteo-France and Universite Paul Sabatier
2 !SFX_LIC This is part of the SURFEX software governed by the CeCILL-C licence
3 !SFX_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
4 !SFX_LIC for details. version 1.
5 !GLT_LIC The GELATO model is a seaice model used in stand-alone or embedded mode.
6 !GLT_LIC It has been developed by Meteo-France. The holder of GELATO is Meteo-France.
7 !GLT_LIC
8 !GLT_LIC This software is governed by the CeCILL-C license under French law and biding
9 !GLT_LIC by the rules of distribution of free software. See the CeCILL-C_V1-en.txt
10 !GLT_LIC (English) and CeCILL-C_V1-fr.txt (French) for details. The CeCILL is a free
11 !GLT_LIC software license, explicitly compatible with the GNU GPL
12 !GLT_LIC (see http://www.gnu.org/licenses/license-list.en.html#CeCILL)
13 !GLT_LIC
14 !GLT_LIC The CeCILL-C licence agreement grants users the right to modify and re-use the
15 !GLT_LIC software governed by this free software license. The exercising of this right
16 !GLT_LIC is conditional upon the obligation to make available to the community the
17 !GLT_LIC modifications made to the source code of the software so as to contribute to
18 !GLT_LIC its evolution.
19 !GLT_LIC
20 !GLT_LIC In consideration of access to the source code and the rights to copy, modify
21 !GLT_LIC and redistribute granted by the license, users are provided only with a limited
22 !GLT_LIC warranty and the software's author, the holder of the economic rights, and the
23 !GLT_LIC successive licensors only have limited liability. In this respect, the risks
24 !GLT_LIC associated with loading, using, modifying and/or developing or reproducing the
25 !GLT_LIC software by the user are brought to the user's attention, given its Free
26 !GLT_LIC Software status, which may make it complicated to use, with the result that its
27 !GLT_LIC use is reserved for developers and experienced professionals having in-depth
28 !GLT_LIC computer knowledge. Users are therefore encouraged to load and test the
29 !GLT_LIC suitability of the software as regards their requirements in conditions enabling
30 !GLT_LIC the security of their systems and/or data to be ensured and, more generally, to
31 !GLT_LIC use and operate it in the same conditions of security.
32 !GLT_LIC
33 !GLT_LIC The GELATO sofware is cureently distibuted with the SURFEX software, available at
34 !GLT_LIC http://www.cnrm.meteo.fr/surfex. The fact that you download the software deemed that
35 !GLT_LIC you had knowledge of the CeCILL-C license and that you accept its terms.
36 !GLT_LIC Attempts to use this software in a way not complying with CeCILL-C license
37 !GLT_LIC may lead to prosecution.
38 !GLT_LIC
39 !* Solves vertical heat diffusion for an ice + snow slab.
40 !
41 ! Created : 02/2010 (D. Salas y Melia)
42 ! Modified: 03/2010 (D. Salas y Melia)
43 ! Now a single routine solves the heat diffusion scheme either for an ice
44 ! slab or for an ice + snow slab
45 !
46 !THXS_SFX!MODULE modi_glt_vhdslab_r
47 !THXS_SFX!INTERFACE
48 !THXS_SFX!!
49 !THXS_SFX!SUBROUTINE glt_vhdslab_r &
50 !THXS_SFX! ( kit,pnsftop,pswtra,pderiv, &
51 !THXS_SFX! pcondb,ptsfa,pqtopmelt,pdh,ptsia,osmelt,osnow )
52 !THXS_SFX! USE modd_glt_const_thm
53 !THXS_SFX! USE modd_glt_param
54 !THXS_SFX! USE modd_glt_vhd
55 !THXS_SFX! USE modi_glt_invert
56 !THXS_SFX! INTEGER, INTENT(in) :: &
57 !THXS_SFX! kit
58 !THXS_SFX! REAL, INTENT(in) :: &
59 !THXS_SFX! pnsftop
60 !THXS_SFX! REAL, DIMENSION(nl), INTENT(in) :: &
61 !THXS_SFX! pswtra
62 !THXS_SFX! REAL, INTENT(inout) :: &
63 !THXS_SFX! pderiv
64 !THXS_SFX! REAL, INTENT(out) :: &
65 !THXS_SFX! pcondb,ptsfa,pqtopmelt
66 !THXS_SFX! REAL, DIMENSION(nl), INTENT(out) :: &
67 !THXS_SFX! pdh
68 !THXS_SFX! REAL, DIMENSION(0:nilay), INTENT(out) :: &
69 !THXS_SFX! ptsia
70 !THXS_SFX! LOGICAL, INTENT(out) :: &
71 !THXS_SFX! osmelt
72 !THXS_SFX! LOGICAL, OPTIONAL, INTENT(in) :: &
73 !THXS_SFX! osnow
74 !THXS_SFX!END SUBROUTINE glt_vhdslab_r
75 !THXS_SFX!!
76 !THXS_SFX!END INTERFACE
77 !THXS_SFX!END MODULE modi_glt_vhdslab_r
78 !
79 ! --------------------- END MODULE modi_glt_vhdslab_r -----------------------
80 !
81 !
82 ! -----------------------------------------------------------------------
83 ! ----------------------- SUBROUTINE glt_vhdslab_r --------------------------
84 !
85 SUBROUTINE glt_vhdslab_r &
86  ( kit,pnsftop,pswtra,pderiv, &
87  pcondb,ptsfa,pqtopmelt,pdh,ptsia,osmelt,osnow )
88 !
90  USE modd_glt_param, only : nilay, nl
91  USE modd_glt_vhd
92  USE modi_glt_invert
93 !
94  IMPLICIT NONE
95 !
96  INTEGER, INTENT(in) :: &
97  kit
98  REAL, INTENT(in) :: &
99  pnsftop
100  REAL, DIMENSION(nl), INTENT(in) :: &
101  pswtra
102  REAL, INTENT(inout) :: &
103  pderiv
104  REAL, INTENT(out) :: &
105  pcondb,ptsfa,pqtopmelt
106  REAL, DIMENSION(nilay+1), INTENT(out) :: &
107  pdh
108  REAL, DIMENSION(0:nilay), INTENT(out) :: &
109  ptsia
110  LOGICAL, INTENT(out) :: &
111  osmelt
112  LOGICAL, OPTIONAL, INTENT(in) :: &
113  osnow
114 !
115 !
116 ! 1.2. Local variables
117 ! --------------------
118 !
119  REAL, PARAMETER :: &
120  pptsfmin=-50.
121  LOGICAL :: &
122  llmeltop,gsnow
123  LOGICAL, DIMENSION(0:nilay) :: &
124  llmelt
125  INTEGER :: &
126  jl,itop
127  REAL :: &
128  zderiv,ztsm,zmelt,zdht,zdqdt,zbl
129  REAL, DIMENSION(0:nilay+1) :: &
130  zx,zy
131  REAL, DIMENSION(0:nilay+1,0:nilay+1) :: &
132  zmat,zmatinv
133 !
134 !
135 !
136 ! 1. Initializations
137 ! ===================
138 !
139 ! 1.1. Build the M matrix of the system (M*x = y) and glt_invert it
140 ! -------------------------------------------------------------
141 !
142 ! Snow layer boolean
143  IF ( present(osnow) ) THEN
144  gsnow = osnow
145  ELSE
146  gsnow = .false.
147  ENDIF
148  IF ( gsnow ) THEN
149  itop = 0
150  ELSE
151  itop = 1
152  ENDIF
153 !
154 ! Surface melting temperature
155  ztsm = ztsi_m0(itop)
156 !
157 ! Surface melting boolean
158 ! MAJOR MODIFICATION SINCE IPCC VERSION
159 ! We assume the final temperature will probably correspond to melting
160 ! if current temperature is melting point AND top conduction flux
161 ! is positive (in principle, a surface gradient condition would be more
162 ! correct...)
163  llmeltop = ( ztsfb>=ztsm .AND. zcondt_m>0. )
164 !! lltempcond = ( llmelt .AND. ABS(znsftop0-zcondt_m)>epsil1 )
165 !
166 ! Ice and snow slab melting boolean
167 ! IF ( kit>2 ) THEN
168 ! llmelt = ( ztsib>=ztsi_m0 )
169 ! ELSE
170  llmelt(:) = .false.
171 ! ENDIF
172 !
173 ! Define the matrix
174  zmat(:,:) = 0.
175 !
176  IF ( .NOT. gsnow ) zmat(0,0) = 1.
177 !
178  IF ( llmeltop ) THEN
179  IF (lp4) THEN
180  WRITE(noutlu,*) '=================================='
181  WRITE(noutlu,*) ' Temp. condition: ztsfb=',ztsfb
182  WRITE(noutlu,*) '=================================='
183  ENDIF
184  zmat(itop,itop) = 1.
185  zmat(itop,itop+1) = 0.
186  zmat(itop+1,itop) = 0.
187  ELSE
188  IF (lp4) THEN
189  WRITE(noutlu,*) '=================================='
190  WRITE(noutlu,*) ' Flux condition : ztsfb=',ztsfb
191  WRITE(noutlu,*) ' zcondt_m=',zcondt_m
192  WRITE(noutlu,*) '=================================='
193  ENDIF
194  zmat(itop,itop) = pderiv - zkodzi(itop)
195  zmat(itop,itop+1) = zkodzi(itop)
196  IF ( .NOT.llmelt(itop) ) zmat(itop+1,itop) = -zetaik(itop)
197  ENDIF
198 !
199  IF ( llmelt(itop) ) THEN
200  zmat(itop+1,itop+1) = 1.
201  ELSE
202  zmat(itop+1,itop+1) = 1. + zetaik(itop) + zetaikp1(itop)
203  zmat(itop+1,itop+2) = -zetaikp1(itop)
204  ENDIF
205 !
206  DO jl=itop+2,nilay
207  IF ( llmelt(jl-1) ) THEN
208  zmat(jl,jl) = 1.
209  ELSE
210  zmat(jl,jl-1) = -zetaik(jl-1)
211  zmat(jl,jl) = 1. + zetaik(jl-1) + zetaikp1(jl-1)
212  zmat(jl,jl+1) = -zetaikp1(jl-1)
213  ENDIF
214  END DO
215 !
216  IF ( llmelt(nilay) ) THEN
217  zmat(nilay+1,nilay+1) = 1.
218  ELSE
219  zmat(nilay+1,nilay) = -zetaik(nilay) + zg2*zetaikp1(nilay)
220  zmat(nilay+1,nilay+1) = 1. + zetaik(nilay) + zg1*zetaikp1(nilay)
221  ENDIF
222 !
223 ! .. Print the matrix on request
224 !
225  IF ( lp5 .OR. llredo ) THEN
226  WRITE(noutlu,*) &
227  '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
228  WRITE(noutlu,*)
229  WRITE(noutlu,*) 'Initial matrix M'
230  DO jl=itop,nilay+1
231  WRITE(noutlu,*) zmat(jl,:)
232  END DO
233  ENDIF
234 !
235 ! .. Invert the matrix
236 !
237  zmatinv = zmat
238  CALL glt_invert( 1,zmatinv )
239 !
240 !
241 ! 1.2. Build the y vector of the system to solve (M*x = y)
242 ! --------------------------------------------------------
243 !
244  IF ( .NOT. gsnow ) zy(0) = 0.
245 !
246  IF ( llmeltop ) THEN
247  zy(itop) = ztsm
248  IF ( llmelt(itop) ) THEN
249  zy(itop+1) = ztsi_m0(itop)
250  ELSE
251  zy(itop+1) = ztsi0(itop) + zetaik(itop)*ztsm + &
252  xswhdfr*pswtra(nilay+1-itop)*zetai(itop)
253  ENDIF
254  ELSE
255  zy(itop) = -znsftop0 + pderiv*ztsf0
256  IF ( llmelt(itop) ) THEN
257  zy(itop+1) = ztsi_m0(itop)
258  ELSE
259  zy(itop+1) = ztsi0(itop) + &
260  xswhdfr*pswtra(nilay+1-itop)*zetai(itop)
261  ENDIF
262  ENDIF
263  DO jl=itop+2,nilay
264  IF ( llmelt(jl-1) ) THEN
265  zy(jl) = ztsi_m0(jl-1)
266  ELSE
267  zy(jl) = ztsi0(jl-1) + xswhdfr*pswtra(nilay+2-jl)*zetai(jl-1)
268  ENDIF
269  END DO
270  IF ( llmelt(nilay) ) THEN
271  zy(nilay+1) = ztsi_m0(nilay)
272  ELSE
273  zy(nilay+1) = (zg1+zg2)*zetaikp1(nilay)*zmlf + ztsi0(nilay) + &
274  xswhdfr*pswtra(1)*zetai(nilay)
275  ENDIF
276 !
277 !
278 ! 1.3. Solve the system
279 ! ----------------------
280 !
281 ! .. Now we update the vertical temperature profile
282 !
283  IF ( lp4 .OR. llredo ) THEN
284  WRITE(noutlu,*)
285  WRITE(noutlu,*) 'Initial vector'
286  WRITE(noutlu,*) zy
287  WRITE(noutlu,*) 'Initial vtp'
288  WRITE(noutlu,*) ztsi0(:)
289  ENDIF
290 !
291  DO jl=0,nilay+1
292  zx(jl) = sum( zmatinv(jl,:)*zy(:) )
293  END DO
294 !
295  IF ( lp4 .OR. llredo ) THEN
296  WRITE(noutlu,*)
297  WRITE(noutlu,*) 'Initial matrix by found vector:'
298  DO jl=0,nilay+1
299  WRITE(noutlu,*) sum( zmat(jl,:)*zx(:) )
300  END DO
301  WRITE(noutlu,*)
302  ENDIF
303 !
304 !
305 ! 1.4. Update variables
306 ! ---------------------
307 !
308 ! .. Surface temperature
309  ptsfa = max( zx(itop),pptsfmin )
310 !
311 ! .. Sea ice (and snow) vertical temperature profile
312  DO jl=0,nilay
313  ptsia(jl) = zx(jl+1)
314  END DO
315 !
316 ! .. Flux at the bottom of the slab
317  pcondb = &
318  zkodzi(nilay+1)*( zg1*( zmlf-ptsia(nilay) )+ &
319  zg2*( zmlf-ptsia(nilay-1) ) )
320 !
321 ! .. (melting case): derive top conductive heat flux
322  llmeltop = ( ptsfa>=ztsm )
323  IF ( llmeltop ) THEN
324  zcondt_m = -zkodzi(itop)* ( ptsia(itop) - ptsfa )
325  ELSE
326  zcondt_m = pnsftop
327  ENDIF
328 ! ( AMIN1(ptsia(itop),ztsm) - AMIN1(ptsfa,ztsm) )
329 !! lltempcond = ( llmelt .AND. ABS(znsftop0-zcondt_m)>epsil1 )
330 !
331 ! .. Additional surface heat flux (due to the sensitivity of surface heat flux
332 ! to changes in surface temperature)
333  IF ( llmeltop ) THEN
334  zderiv = 0.
335  ELSE
336  zderiv = pderiv
337  ENDIF
338 !
339 ! .. Compute lost dQ/dT * Dt due to surface T limitation
340 ! (and add it to bottom conduction)
341  zdqdt = zderiv*min( zx(itop)-pptsfmin,0. )
342  pcondb = pcondb + zdqdt
343 !
344 ! .. Collect all the energy corresponding to temperatures higher than
345 ! melting point
346 ! - in sea ice
347  zmelt = sum( zinvetai(:)*max(ptsia(:)-ztsi_m0(:),0.) )
348 !! write(noutlu,*) 'zmelt =',zmelt
349 !! write(noutlu,*) 'ptsia =',ptsia
350  ptsia(:) = min( ptsia(:),ztsi_m0(:) )
351 !! write(noutlu,*) 'ptsia =',ptsia
352 !
353 ! .. Deduce which part of the top non-solar flux is devoted to melting
354  pqtopmelt = znsftop0-zcondt_m+zmelt
355 !! pqtopmelt = zmelt
356 !! write(noutlu,*) 'znsftop0 =',znsftop0
357 !! write(noutlu,*) 'zcondt_m =',zcondt_m
358 !
359  IF ( lp4 .OR. llredo ) THEN
360  WRITE(noutlu,*) 'Previous surface temperature =',ztsf0
361  WRITE(noutlu,*) 'New surface temperature =',ptsfa
362  WRITE(noutlu,*) 'Previous vtp:'
363  WRITE(noutlu,*) ztsi0
364  WRITE(noutlu,*) 'New vtp :'
365  WRITE(noutlu,*) ptsia
366  WRITE(noutlu,*) 'zcondt =',znsftop0
367  ENDIF
368 !
369 ! .. Melting surface boolean
370  osmelt = llmeltop
371 !
372 !
373 ! 1.5. Energy conservation check
374 ! -------------------------------
375 !
376  IF ( lp3 .OR. llredo ) THEN
377 !
378  WRITE(noutlu,*)
379  WRITE(noutlu,*) 'Energy check'
380  WRITE(noutlu,*) '============='
381  WRITE(noutlu,*)
382  WRITE(noutlu,*) 'Left hand-side (vhdslab):'
383  WRITE(noutlu,*) '--------------------------'
384  WRITE(noutlu,*) ' Non-solar heat flux at the top:', &
385  pnsftop
386  WRITE(noutlu,*) ' Absorbed solar heat flux:', &
387  xswhdfr * sum(pswtra(1:nilay+1-itop))
388  WRITE(noutlu,*) ' Cond. heat flux at the bottom:', &
389  pcondb
390  WRITE(noutlu,*) &
391  ' Additional heat flux at the top dQ/dT*(Tnew-Told):', &
392  zderiv*( ptsfa-ztsf0 )
393 !! WRITE(noutlu,*) ' Cond. heat flux at the top:', &
394 !! zcondt_m
395  WRITE(noutlu,*)
396  WRITE(noutlu,*) 'Right hand-side:'
397  WRITE(noutlu,*) '-----------------'
398  zdht = sum( ( ptsia(:)-ztsi0(:) ) * zinvetai(:) )
399  WRITE(noutlu,*) ' Enthalpy change per time unit:', &
400  zdht
401  WRITE(noutlu,*) ' Top melting flux:', &
402  pqtopmelt
403 !
404 !! WRITE(noutlu,*) 'Enthalpy change per time unit (layers):'
405 !! WRITE(noutlu,*) '----------------------------------------'
406 !! WRITE(noutlu,*) ( ptsia(:)-ztsi0(:) ) * zinvetai(:)
407 !! WRITE(noutlu,*)
408  WRITE(noutlu,*)
409  WRITE(noutlu,*) &
410  'Left hand-side minus right-hand side'
411  WRITE(noutlu,*) &
412  '-------------------------------------'
413  zbl = zdht + pqtopmelt - &
414  ( pcondb + xswhdfr*sum(pswtra(1:nilay+1-itop)) + &
415  pnsftop + zderiv*( ptsfa-ztsf0 ) )
416  WRITE(noutlu,*) zbl
417  IF ( abs(zbl)>0.1 ) THEN
418  IF (lwg) THEN
419  WRITE(noutlu,*)'Imbalance'
420  WRITE(noutlu,*)'llmeltop =',llmeltop
421  WRITE(noutlu,*)'gsnow =',gsnow
422  WRITE(noutlu,*)'pqtopmelt=',pqtopmelt
423  WRITE(noutlu,*)'znsftop0 =',znsftop0
424  WRITE(noutlu,*)'-zcondt_m=',-zcondt_m
425  WRITE(noutlu,*)'zmelt =',zmelt
426  ENDIF
427  ENDIF
428 !
429  ENDIF
430 !
431  IF ( lp5 .OR. llredo ) THEN
432 !
433  WRITE(noutlu,*)
434  WRITE(noutlu,*) 'Check the equations'
435  WRITE(noutlu,*) &
436  ' (',itop,') ', &
437 !! ( pderiv-zkodzi(itop) )*ptsfa + zkodzi(itop)*ptsia(itop), &
438 !! pderiv*ztsf0 - pnsftop + pqtopmelt
439  zmat(itop,itop)*ptsfa + zmat(itop,itop+1)*ptsia(itop), &
440 !! pderiv*ztsf0 - pnsftop + pqtopmelt
441  zy(itop)
442  WRITE(noutlu,*) &
443  ' (',itop+1,') ', &
444 !! - zetaik(itop)*ptsfa + &
445 !! ( 1.+zetaik(itop)+zetaikp1(itop) )*ptsia(itop) &
446 !! - zetaikp1(itop)*ptsia(itop+1), &
447  - zmat(itop+1,itop)*ptsfa + &
448  zmat(itop+1,itop+1)*ptsia(itop) &
449  - zmat(itop+1,itop+2)*ptsia(itop+1), &
450  ztsi0(itop)
451 !! write(noutlu,*) '- zetaik(itop)*ptsfa',- zetaik(itop)*ptsfa
452 !! write(noutlu,*) 'ptsfa =',ptsfa
453 !! write(noutlu,*) '( 1.+zetaik(itop)+zetaikp1(itop) )*ptsia(itop)', &
454 !! ( 1.+zetaik(itop)+zetaikp1(itop) )*ptsia(itop)
455 !! write(noutlu,*) 'ptsia(itop) =',ptsia(itop)
456 !! write(noutlu,*) '- zetaikp1(itop)*ptsia(itop+1)', - zetaikp1(itop)*ptsia(itop+1)
457 !! write(noutlu,*) 'ptsia(itop+1) =',ptsia(itop+1)
458 !
459  DO jl=itop+2,nilay
460  WRITE(noutlu,*) &
461  ' (',jl,') ', &
462  - zetaik(jl-1)*ptsia(jl-2) + &
463  ( 1.+zetaik(jl-1)+zetaikp1(jl-1) )*ptsia(jl-1) &
464  - zetaikp1(jl-1)*ptsia(jl), &
465  ztsi0(jl-1)
466  END DO
467 !
468  WRITE(noutlu,*) &
469  ' (',nilay+1,') ', &
470  ( -zetaik(nilay)+zg2*zetaikp1(nilay) )*ptsia(nilay-1) + &
471  ( 1.+zetaik(nilay)+zg1*zetaikp1(nilay) )*ptsia(nilay), &
472  (zg1+zg2)*zetaikp1(nilay)*zmlf + ztsi0(nilay)
473 !
474  ENDIF
475 !
476 ! .. Final update of pderiv
477 !
478  pderiv = zderiv
479 !
480 ! .. Convert gltools_enthalpy change to J.kg-1 of ice
481 !
482  DO jl=1,nilay
483  pdh(jl) = zrhocpsi(nilay+1-jl)/rhoice * &
484  ( ptsia(nilay+1-jl)-ztsi0(nilay+1-jl) )
485  END DO
486  IF ( gsnow ) THEN
487  pdh(nilay+1) = cpice0 * ( ptsia(0)-ztsi0(0) )
488  ELSE
489  pdh(nilay+1) = 0.
490  ENDIF
491 !
492  END SUBROUTINE glt_vhdslab_r
subroutine glt_vhdslab_r(kit, pnsftop, pswtra, pderiv, pcondb, ptsfa, pqtopmelt, pdh, ptsia, osmelt, osnow)
subroutine glt_invert(kdiag, pmat)