source: palm/trunk/SOURCE/surface_layer_fluxes_mod.f90 @ 3833

Last change on this file since 3833 was 3833, checked in by forkel, 5 years ago

removed USE chem_gasphase_mod from chem_modules, apply USE chem_gasphase for nvar, nspec, cs_mech and spc_names instead

  • Property svn:keywords set to Id
File size: 75.0 KB
RevLine 
[1850]1!> @file surface_layer_fluxes_mod.f90
[2000]2!------------------------------------------------------------------------------!
[2696]3! This file is part of the PALM model system.
[1691]4!
[2000]5! PALM is free software: you can redistribute it and/or modify it under the
6! terms of the GNU General Public License as published by the Free Software
7! Foundation, either version 3 of the License, or (at your option) any later
8! version.
[1691]9!
10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13!
14! You should have received a copy of the GNU General Public License along with
15! PALM. If not, see <http://www.gnu.org/licenses/>.
16!
[3655]17! Copyright 1997-2019 Leibniz Universitaet Hannover
[1691]18!
[2000]19!------------------------------------------------------------------------------!
[2696]20!
[1691]21! Current revisions:
[1747]22! ------------------
[1758]23!
[3745]24!
[1692]25! Former revisions:
26! -----------------
27! $Id: surface_layer_fluxes_mod.f90 3833 2019-03-28 15:04:04Z forkel $
[3833]28! added USE chem_gasphase_mod
29!
30! 3787 2019-03-07 08:43:54Z raasch
[3787]31! unused variables removed
32!
33! 3745 2019-02-15 18:57:56Z suehring
[3745]34! Bugfix, missing calculation of 10cm temperature at vertical building walls,
35! required for indoor model
36!
37! 3744 2019-02-15 18:38:58Z suehring
[3685]38! Some interface calls moved to module_interface + cleanup
39!
40! 3668 2019-01-14 12:49:24Z maronga
[3668]41! Removed methods "circular" and "lookup"
42!
43! 3655 2019-01-07 16:51:22Z knoop
[3634]44! OpenACC port for SPEC
45!
46! 3597 2018-12-04 08:40:18Z maronga
[3597]47! Added routine for calculating near surface air potential temperature (moved
48! from urban_surface_mod)
49!
50! 3547 2018-11-21 13:21:24Z suehring
[3547]51! variables documented
52!
53! 3361 2018-10-16 20:39:37Z knoop
[3274]54! Modularization of all bulk cloud physics code components
55!
56! 3271 2018-09-24 08:20:34Z suehring
[3271]57! Comment revised
58!
59! 3157 2018-07-19 21:08:49Z maronga
[3157]60! Added local free convection velocity scale w_lfc in calculation of uvw_abs.
61! This can be switche on/off by the user via the flag namelist parameter
62! use_free_convection_scaling
63!
64! 3152 2018-07-19 13:26:52Z suehring
[3152]65! q_surface is now part of surface structure
66!
67! 3149 2018-07-19 05:48:09Z maronga
[3149]68! Correct accidental last commit
69!
70! 3148 2018-07-19 05:45:25Z maronga
[3147]71! Major bugfix in calculation of Obukhov length
72!
73! 3146 2018-07-18 22:36:19Z maronga
[3130]74! move phi_m from turbulence_closure_mod
75!
76! 3045 2018-05-28 07:55:41Z Giersch
[3045]77! Error message revised
78!
79! 2766 2018-01-22 17:17:47Z kanani
[2766]80! Removed preprocessor directive __chem
81!
82! 2718 2018-01-02 08:49:38Z maronga
[2716]83! Corrected "Former revisions" section
84!
85! 2696 2017-12-14 17:12:51Z kanani
86! - Change in file header (GPL part)
[2696]87! - Implementation of chemistry module (FK)
88! - Added calculation of pt1 and qv1 for all surface types. Added calculation of
89!   pt_surface for default-type surfaces (BM)
90! - Add flag to disable computation of qsws in case of urban surface (MS)
91!
92! 2547 2017-10-16 12:41:56Z schwenkel
[2547]93! extended by cloud_droplets option
94!
95! 2321 2017-07-24 15:57:07Z schwenkel
[2321]96! Bugfix: Correct index in lookup table for Obukhov length
97!
98! 2299 2017-06-29 10:14:38Z suehring
[2299]99! Adjusted for allow separate spinups of LSM and atmosphere code
100!
101! 2292 2017-06-20 09:51:42Z schwenkel
[2292]102! Implementation of new microphysic scheme: cloud_scheme = 'morrison'
103! includes two more prognostic equations for cloud drop concentration (nc) 
104! and cloud water content (qc).
105!
106! 2281 2017-06-13 11:34:50Z suehring
[2281]107! Clean-up unnecessary index access to surface type
108!
109! 2233 2017-05-30 18:08:54Z suehring
[1692]110!
[2233]111! 2232 2017-05-30 17:47:52Z suehring
112! Adjustments to new surface concept
113! OpenMP bugfix
114!
[2119]115! 2118 2017-01-17 16:38:49Z raasch
116! OpenACC directives and related code removed
117!
[2092]118! 2091 2016-12-21 16:38:18Z suehring
119! Bugfix in calculation of vsws ( incorrect linear interpolation of us )
120!
[2077]121! 2076 2016-12-02 13:54:20Z raasch
122! further openmp bugfix for lookup method
123!
[2074]124! 2073 2016-11-30 14:34:05Z raasch
125! openmp bugfix for lookup method
126!
[2038]127! 2037 2016-10-26 11:15:40Z knoop
128! Anelastic approximation implemented
129!
[2012]130! 2011 2016-09-19 17:29:57Z kanani
131! Flag urban_surface is now defined in module control_parameters.
132!
[2008]133! 2007 2016-08-24 15:47:17Z kanani
134! Account for urban surface model in computation of vertical kinematic heatflux
135!
[2001]136! 2000 2016-08-20 18:09:15Z knoop
137! Forced header and separation lines into 80 columns
138!
[1993]139! 1992 2016-08-12 15:14:59Z suehring
140! Minor bug, declaration of look-up index as INTEGER
141!
[1961]142! 1960 2016-07-12 16:34:24Z suehring
143! Treat humidity and passive scalar separately
144!
[1930]145! 1929 2016-06-09 16:25:25Z suehring
146! Bugfix: avoid segmentation fault in case one grid point is horizontally
147! completely surrounded by topography
148!
[1921]149! 1920 2016-05-30 10:50:15Z suehring
150! Avoid segmentation fault (see change in 1915) by different initialization of
151! us instead of adding a very small number in the denominator
152!
[1916]153! 1915 2016-05-27 11:05:02Z suehring
154! Bugfix: avoid segmentation fault in case of most_method = 'circular' at first
155! timestep
156!
[1851]157! 1850 2016-04-08 13:29:27Z maronga
158! Module renamed
159!
160!
[1823]161! 1822 2016-04-07 07:49:42Z hoffmann
162! icloud_scheme replaced by microphysics_*
163!
[1789]164! 1788 2016-03-10 11:01:04Z maronga
165! Added parameter z0q which replaces z0h in the similarity functions for
166! humidity.
167! Syntax layout improved.
168!
[1758]169! 1757 2016-02-22 15:49:32Z maronga
170! Minor fixes.
171!
[1750]172! 1749 2016-02-09 12:19:56Z raasch
173! further OpenACC adjustments
174!
[1748]175! 1747 2016-02-08 12:25:53Z raasch
176! adjustments for OpenACC usage
177!
[1710]178! 1709 2015-11-04 14:47:01Z maronga
179! Bugfix: division by zero could occur when calculating rib at low wind speeds
180! Bugfix: calculation of uv_total for neutral = .T., initial value for ol for
181! neutral = .T.
182!
[1706]183! 1705 2015-11-02 14:28:56Z maronga
184! Typo removed
185!
[1698]186! 1697 2015-10-28 17:14:10Z raasch
187! FORTRAN and OpenMP errors removed
188!
[1697]189! 1696 2015-10-27 10:03:34Z maronga
[1691]190! Modularized and completely re-written version of prandtl_fluxes.f90. In the
191! course of the re-writing two additional methods have been implemented. See
192! updated description.
193!
194! 1551 2015-03-03 14:18:16Z maronga
195! Removed land surface model part. The surface fluxes are now always calculated
196! within prandtl_fluxes, based on the given surface temperature/humidity (which
197! is either provided by the land surface model, by large scale forcing data, or
198! directly prescribed by the user.
199!
200! 1496 2014-12-02 17:25:50Z maronga
201! Adapted for land surface model
202!
203! 1494 2014-11-21 17:14:03Z maronga
204! Bugfixes: qs is now calculated before calculation of Rif. calculation of
205! buoyancy flux in Rif corrected (added missing humidity term), allow use of
206! topography for coupled runs (not tested)
207!
208! 1361 2014-04-16 15:17:48Z hoffmann
209! Bugfix: calculation of turbulent fluxes of rain water content (qrsws) and rain
210! drop concentration (nrsws) added
211!
212! 1340 2014-03-25 19:45:13Z kanani
213! REAL constants defined as wp-kind
214!
215! 1320 2014-03-20 08:40:49Z raasch
216! ONLY-attribute added to USE-statements,
217! kind-parameters added to all INTEGER and REAL declaration statements,
218! kinds are defined in new module kinds,
219! old module precision_kind is removed,
220! revision history before 2012 removed,
221! comment fields (!:) to be used for variable explanations added to
222! all variable declaration statements
223!
224! 1276 2014-01-15 13:40:41Z heinze
225! Use LSF_DATA also in case of Dirichlet bottom boundary condition for scalars
226!
227! 1257 2013-11-08 15:18:40Z raasch
228! openACC "kernels do" replaced by "kernels loop", "loop independent" added
229!
230! 1036 2012-10-22 13:43:42Z raasch
231! code put under GPL (PALM 3.9)
232!
233! 1015 2012-09-27 09:23:24Z raasch
234! OpenACC statements added
235!
236! 978 2012-08-09 08:28:32Z fricke
237! roughness length for scalar quantities z0h added
238!
239! Revision 1.1  1998/01/23 10:06:06  raasch
240! Initial revision
241!
242!
243! Description:
244! ------------
245!> Diagnostic computation of vertical fluxes in the constant flux layer from the
[3668]246!> values of the variables at grid point k=1 based on Newton iteration
[1691]247!>
248!> @todo (re)move large_scale_forcing actions
[2118]249!> @todo check/optimize OpenMP directives
[2696]250!> @todo simplify if conditions (which flux need to be computed in which case)
[1691]251!------------------------------------------------------------------------------!
252 MODULE surface_layer_fluxes_mod
253
254    USE arrays_3d,                                                             &
[2292]255        ONLY:  e, kh, nc, nr, pt, q, ql, qc, qr, s, u, v, vpt, w, zu, zw,      &
[3274]256               drho_air_zw, rho_air_zw, d_exner
[1691]257
[3274]258    USE basic_constants_and_equations_mod,                                     &
[3361]259        ONLY:  g, kappa, lv_d_cp, pi, rd_d_rv
[3274]260
[3833]261    USE chem_gasphase_mod,                                                     &
262        ONLY:  nvar
263
[2696]264    USE chem_modules,                                                          &
265        ONLY:  constant_csflux, nvar
266
[1691]267    USE cpulog
268
269    USE control_parameters,                                                    &
[3274]270        ONLY:  air_chemistry, cloud_droplets,                                  &
271               constant_heatflux, constant_scalarflux,                         &
[3597]272               constant_waterflux, coupling_mode, do_output_at_2m, humidity,   &
273               ibc_e_b, ibc_pt_b, indoor_model, initializing_actions,          &
[2232]274               intermediate_timestep_count, intermediate_timestep_count_max,   &
[3274]275               land_surface, large_scale_forcing, lsf_surf, message_string,    &
[3668]276               neutral, passive_scalar, pt_surface, q_surface,                 &
[2292]277               run_coupled, surface_pressure, simulated_time, terminate_run,   &
[3157]278               time_since_reference_point, urban_surface,                      &
279               use_free_convection_scaling, zeta_max, zeta_min
[1691]280
[2232]281    USE grid_variables,                                                        &
282        ONLY:  dx, dy 
283
[1691]284    USE indices,                                                               &
[2232]285        ONLY:  nxl, nxr, nys, nyn, nzb
[1691]286
287    USE kinds
288
[3274]289    USE bulk_cloud_model_mod,                                                  &
290        ONLY: bulk_cloud_model, microphysics_morrison, microphysics_seifert
291
[1691]292    USE pegrid
293
294    USE land_surface_model_mod,                                                &
[2232]295        ONLY:  aero_resist_kray, skip_time_do_lsm
[2011]296
[2232]297    USE surface_mod,                                                           &
298        ONLY :  surf_def_h, surf_def_v, surf_lsm_h, surf_lsm_v, surf_type,     &
299                surf_usm_h, surf_usm_v
[2007]300       
[1691]301
302    IMPLICIT NONE
303
[1992]304    INTEGER(iwp) ::  i              !< loop index x direction
305    INTEGER(iwp) ::  j              !< loop index y direction
306    INTEGER(iwp) ::  k              !< loop index z direction
[2232]307    INTEGER(iwp) ::  l              !< loop index for surf type
[1691]308
[2232]309    INTEGER(iwp), PARAMETER ::  num_steps = 15000  !< number of steps in the lookup table
[1691]310
[2232]311    LOGICAL      ::  coupled_run       !< Flag for coupled atmosphere-ocean runs
312    LOGICAL      ::  downward = .FALSE.!< Flag indicating downward-facing horizontal surface
313    LOGICAL      ::  mom_uv  = .FALSE. !< Flag indicating calculation of usvs and vsus at vertical surfaces
314    LOGICAL      ::  mom_w   = .FALSE. !< Flag indicating calculation of wsus and wsvs at vertical surfaces
315    LOGICAL      ::  mom_tke = .FALSE. !< Flag indicating calculation of momentum fluxes at vertical surfaces used for TKE production
316    LOGICAL      ::  surf_vertical     !< Flag indicating vertical surfaces
[1691]317
318    REAL(wp)     ::  e_s,               & !< Saturation water vapor pressure
319                     ol_max = 1.0E6_wp, & !< Maximum Obukhov length
320                     z_mo                 !< Height of the constant flux layer where MOST is assumed
321
[2232]322    TYPE(surf_type), POINTER ::  surf     !< surf-type array, used to generalize subroutines
[1691]323
[2232]324
[1691]325    SAVE
326
327    PRIVATE
328
[3130]329    PUBLIC init_surface_layer_fluxes, phi_m, surface_layer_fluxes
[1691]330
331    INTERFACE init_surface_layer_fluxes
332       MODULE PROCEDURE init_surface_layer_fluxes
333    END INTERFACE init_surface_layer_fluxes
334
[3130]335    INTERFACE phi_m
336       MODULE PROCEDURE phi_m
337    END INTERFACE phi_m
338
[1691]339    INTERFACE surface_layer_fluxes
340       MODULE PROCEDURE surface_layer_fluxes
341    END INTERFACE surface_layer_fluxes
342
343
344 CONTAINS
345
346
347!------------------------------------------------------------------------------!
348! Description:
349! ------------
350!> Main routine to compute the surface fluxes
351!------------------------------------------------------------------------------!
352    SUBROUTINE surface_layer_fluxes
353
354       IMPLICIT NONE
355
[3547]356       surf_vertical = .FALSE. !< flag indicating vertically orientated surface elements
357       downward      = .FALSE. !< flag indicating downward-facing surface elements
[1691]358!
[2696]359!--    Derive potential temperature and specific humidity at first grid level
360!--    from the fields pt and q
[2232]361!
[2696]362!--    First call for horizontal default-type surfaces (l=0 - upward facing,
363!--    l=1 - downward facing)
364       DO  l = 0, 1
365          IF ( surf_def_h(l)%ns >= 1  )  THEN
366             surf => surf_def_h(l)
367             CALL calc_pt_q
[3146]368             IF ( .NOT. neutral )  THEN
369                CALL calc_pt_surface
370                IF ( humidity )  THEN
[3152]371                   CALL calc_q_surface
[3146]372                   CALL calc_vpt_surface
373                ENDIF
374             ENDIF
[2696]375          ENDIF
376       ENDDO
[2232]377!
[2696]378!--    Call for natural-type horizontal surfaces
379       IF ( surf_lsm_h%ns >= 1  )  THEN
380          surf => surf_lsm_h
381          CALL calc_pt_q
382       ENDIF
383
384!
385!--    Call for urban-type horizontal surfaces
386       IF ( surf_usm_h%ns >= 1  )  THEN
387          surf => surf_usm_h
388          CALL calc_pt_q
389       ENDIF
390
391!
392!--    Call for natural-type vertical surfaces
393       DO  l = 0, 3
394          IF ( surf_lsm_v(l)%ns >= 1  )  THEN
395             surf => surf_lsm_v(l)
[2232]396             CALL calc_pt_q
397          ENDIF
[2696]398
[3146]399!--       Call for urban-type vertical surfaces
[2696]400          IF ( surf_usm_v(l)%ns >= 1  )  THEN
401             surf => surf_usm_v(l)
[2232]402             CALL calc_pt_q
403          ENDIF
[2696]404       ENDDO
[1691]405
406!
407!--    First, calculate the new Obukhov length, then new friction velocity,
408!--    followed by the new scaling parameters (th*, q*, etc.), and the new
[3668]409!--    surface fluxes if required. Note, each routine is called for different surface types.
[2232]410!--    First call for default-type horizontal surfaces, for natural- and
411!--    urban-type surfaces. Note, at this place only upward-facing horizontal
[3668]412!--    surfaces are treated.
413
[2232]414!
[3668]415!--    Default-type upward-facing horizontal surfaces
416       IF ( surf_def_h(0)%ns >= 1  )  THEN
417          surf => surf_def_h(0)
418          CALL calc_uvw_abs
419          IF ( .NOT. neutral )  CALL calc_ol
420          CALL calc_us
421          CALL calc_scaling_parameters
422          CALL calc_surface_fluxes
423          IF ( do_output_at_2m )  THEN
424             CALL calc_pt_near_surface ( '2m' )
[1691]425          ENDIF
[3668]426       ENDIF
[1691]427!
[3668]428!--    Natural-type horizontal surfaces
429       IF ( surf_lsm_h%ns >= 1  )  THEN
430          surf => surf_lsm_h
431          CALL calc_uvw_abs
432          IF ( .NOT. neutral )  CALL calc_ol
433          CALL calc_us
434          CALL calc_scaling_parameters
435          CALL calc_surface_fluxes
436          IF ( do_output_at_2m )  THEN
437             CALL calc_pt_near_surface ( '2m' )
[2232]438          ENDIF
[3668]439       ENDIF
[2232]440!
[3668]441!--    Urban-type horizontal surfaces
442       IF ( surf_usm_h%ns >= 1  )  THEN
443          surf => surf_usm_h
444          CALL calc_uvw_abs
445          IF ( .NOT. neutral )  CALL calc_ol
446          CALL calc_us
447          CALL calc_scaling_parameters
448          CALL calc_surface_fluxes
449          IF ( do_output_at_2m )  THEN
450             CALL calc_pt_near_surface ( '2m' )
[2232]451          ENDIF
[3744]452!
453!--       Calculate 10cm temperature, required in indoor model
454          IF ( indoor_model )  CALL calc_pt_near_surface ( '10cm' )
[3668]455       ENDIF
[1691]456
[2232]457!
458!--    Treat downward-facing horizontal surfaces. Note, so far, these are
459!--    always default type. Stratification is not considered
460!--    in this case, hence, no further distinction between different
461!--    most_method is required. 
462       IF ( surf_def_h(1)%ns >= 1  )  THEN
463          downward = .TRUE.
464          surf => surf_def_h(1)
465          CALL calc_uvw_abs
[1691]466          CALL calc_us
467          CALL calc_surface_fluxes
[2232]468          downward = .FALSE.
[1691]469       ENDIF
[2232]470!
471!--    Calculate surfaces fluxes at vertical surfaces for momentum
472!--    and subgrid-scale TKE.
473!--    No stability is considered. Therefore, scaling parameters and Obukhov-
474!--    length do not need to be calculated and no distinction in 'circular',
475!--    'Newton' or 'lookup' is necessary so far.
476!--    Note, this will change if stability is once considered.
477       surf_vertical = .TRUE.
478!
479!--    Calculate horizontal momentum fluxes at north- and south-facing
480!--    surfaces(usvs).
481!--    For default-type surfaces
482       mom_uv = .TRUE. 
483       DO  l = 0, 1
484          IF ( surf_def_v(l)%ns >= 1  )  THEN
485             surf => surf_def_v(l)
486!
487!--          Compute surface-parallel velocity
488             CALL calc_uvw_abs_v_ugrid
489!
490!--          Compute respective friction velocity on staggered grid
491             CALL calc_us
492!
493!--          Compute respective surface fluxes for momentum and TKE
494             CALL calc_surface_fluxes
495          ENDIF
496       ENDDO
497!
498!--    For natural-type surfaces. Please note, even though stability is not
499!--    considered for the calculation of momentum fluxes at vertical surfaces,
500!--    scaling parameters and Obukov length are calculated nevertheless in this
501!--    case. This is due to the requirement of ts in parameterization of heat
502!--    flux in land-surface model in case of aero_resist_kray is not true.
503       IF ( .NOT. aero_resist_kray )  THEN
[3668]504          DO  l = 0, 1
505             IF ( surf_lsm_v(l)%ns >= 1  )  THEN
506                surf => surf_lsm_v(l)
[2232]507!
[3668]508!--             Compute surface-parallel velocity
509                CALL calc_uvw_abs_v_ugrid
[2232]510!
[3668]511!--             Compute Obukhov length
512                IF ( .NOT. neutral )  CALL calc_ol
[2232]513!
[3668]514!--             Compute respective friction velocity on staggered grid
515                CALL calc_us
[2232]516!
[3668]517!--             Compute scaling parameters
518                CALL calc_scaling_parameters
[2232]519!
[3668]520!--             Compute respective surface fluxes for momentum and TKE
521                CALL calc_surface_fluxes
522             ENDIF
523          ENDDO
[2232]524!
525!--    No ts is required, so scaling parameters and Obukhov length do not need
526!--    to be computed.
527       ELSE
528          DO  l = 0, 1
529             IF ( surf_lsm_v(l)%ns >= 1  )  THEN
530                surf => surf_lsm_v(l)
531!   
532!--             Compute surface-parallel velocity
533                CALL calc_uvw_abs_v_ugrid
534!
535!--             Compute respective friction velocity on staggered grid
536                CALL calc_us
537!
538!--             Compute respective surface fluxes for momentum and TKE
539                CALL calc_surface_fluxes
540             ENDIF
541          ENDDO
542       ENDIF
543!
544!--    For urban-type surfaces
545       DO  l = 0, 1
546          IF ( surf_usm_v(l)%ns >= 1  )  THEN
547             surf => surf_usm_v(l)
548!
549!--          Compute surface-parallel velocity
550             CALL calc_uvw_abs_v_ugrid
551!
552!--          Compute respective friction velocity on staggered grid
553             CALL calc_us
554!
555!--          Compute respective surface fluxes for momentum and TKE
556             CALL calc_surface_fluxes
[3744]557!
558!--          Calculate 10cm temperature, required in indoor model
559             IF ( indoor_model )  CALL calc_pt_near_surface ( '10cm' )
[2232]560          ENDIF
561       ENDDO
562!
563!--    Calculate horizontal momentum fluxes at east- and west-facing
564!--    surfaces (vsus).
565!--    For default-type surfaces
566       DO  l = 2, 3
567          IF ( surf_def_v(l)%ns >= 1  )  THEN
568             surf => surf_def_v(l)
569!
570!--          Compute surface-parallel velocity
571             CALL calc_uvw_abs_v_vgrid
572!
573!--          Compute respective friction velocity on staggered grid
574             CALL calc_us
575!
576!--          Compute respective surface fluxes for momentum and TKE
577             CALL calc_surface_fluxes
[3744]578             
[2232]579          ENDIF
580       ENDDO
581!
582!--    For natural-type surfaces. Please note, even though stability is not
583!--    considered for the calculation of momentum fluxes at vertical surfaces,
584!--    scaling parameters and Obukov length are calculated nevertheless in this
585!--    case. This is due to the requirement of ts in parameterization of heat
586!--    flux in land-surface model in case of aero_resist_kray is not true.
587       IF ( .NOT. aero_resist_kray )  THEN
[3668]588          DO  l = 2, 3
589             IF ( surf_lsm_v(l)%ns >= 1  )  THEN
590                surf => surf_lsm_v(l)
[2232]591!
[3668]592!--             Compute surface-parallel velocity
593                CALL calc_uvw_abs_v_vgrid
[2232]594!
[3668]595!--             Compute Obukhov length
596                IF ( .NOT. neutral )  CALL calc_ol
[2232]597!
[3668]598!--             Compute respective friction velocity on staggered grid
599                CALL calc_us
[2232]600!
[3668]601!--             Compute scaling parameters
602                CALL calc_scaling_parameters
[2232]603!
[3668]604!--             Compute respective surface fluxes for momentum and TKE
605                CALL calc_surface_fluxes
606             ENDIF
607          ENDDO
[2232]608       ELSE
609          DO  l = 2, 3
610             IF ( surf_lsm_v(l)%ns >= 1  )  THEN
611                surf => surf_lsm_v(l)
612!   
613!--             Compute surface-parallel velocity
614                CALL calc_uvw_abs_v_vgrid
615!
616!--             Compute respective friction velocity on staggered grid
617                CALL calc_us
618!
619!--             Compute respective surface fluxes for momentum and TKE
620                CALL calc_surface_fluxes
621             ENDIF
622          ENDDO
623       ENDIF
624!
625!--    For urban-type surfaces
626       DO  l = 2, 3
627          IF ( surf_usm_v(l)%ns >= 1  )  THEN
628             surf => surf_usm_v(l)
629!
630!--          Compute surface-parallel velocity
631             CALL calc_uvw_abs_v_vgrid
632!
633!--          Compute respective friction velocity on staggered grid
634             CALL calc_us
635!
636!--          Compute respective surface fluxes for momentum and TKE
637             CALL calc_surface_fluxes
[3744]638!
639!--          Calculate 10cm temperature, required in indoor model             
640             IF ( indoor_model )  CALL calc_pt_near_surface ( '10cm' )
[2232]641          ENDIF
642       ENDDO
643       mom_uv = .FALSE.
644!
645!--    Calculate horizontal momentum fluxes of w (wsus and wsvs) at vertial
646!--    surfaces.
647       mom_w = .TRUE.
648!
649!--    Default-type surfaces
650       DO  l = 0, 3
651          IF ( surf_def_v(l)%ns >= 1  )  THEN
652             surf => surf_def_v(l)
653             CALL calc_uvw_abs_v_wgrid
654             CALL calc_us
655             CALL calc_surface_fluxes
656          ENDIF
657       ENDDO 
658!
659!--    Natural-type surfaces
660       DO  l = 0, 3
661          IF ( surf_lsm_v(l)%ns >= 1  )  THEN
662             surf => surf_lsm_v(l)
663             CALL calc_uvw_abs_v_wgrid
664             CALL calc_us
665             CALL calc_surface_fluxes
666          ENDIF
667       ENDDO 
668!
669!--    Urban-type surfaces
670       DO  l = 0, 3
671          IF ( surf_usm_v(l)%ns >= 1  )  THEN
672             surf => surf_usm_v(l)
673             CALL calc_uvw_abs_v_wgrid
674             CALL calc_us
675             CALL calc_surface_fluxes
676          ENDIF
677       ENDDO 
678       mom_w = .FALSE.   
679!
680!--    Calculate momentum fluxes usvs, vsus, wsus and wsvs at vertical
681!--    surfaces for TKE production. Note, here, momentum fluxes are defined
682!--    at grid center and are not staggered as before.
683       mom_tke = .TRUE.
684!
685!--    Default-type surfaces
686       DO  l = 0, 3
687          IF ( surf_def_v(l)%ns >= 1  )  THEN
688             surf => surf_def_v(l)
689             CALL calc_uvw_abs_v_sgrid
690             CALL calc_us
691             CALL calc_surface_fluxes
692          ENDIF
693       ENDDO 
694!
695!--    Natural-type surfaces
696       DO  l = 0, 3
697          IF ( surf_lsm_v(l)%ns >= 1  )  THEN
698             surf => surf_lsm_v(l)
699             CALL calc_uvw_abs_v_sgrid
700             CALL calc_us
701             CALL calc_surface_fluxes
702          ENDIF
703       ENDDO 
704!
705!--    Urban-type surfaces
706       DO  l = 0, 3
707          IF ( surf_usm_v(l)%ns >= 1  )  THEN
708             surf => surf_usm_v(l)
709             CALL calc_uvw_abs_v_sgrid
710             CALL calc_us
711             CALL calc_surface_fluxes
712          ENDIF
713       ENDDO 
714       mom_tke = .FALSE.
715 
[1691]716
717    END SUBROUTINE surface_layer_fluxes
718
719
720!------------------------------------------------------------------------------!
721! Description:
722! ------------
723!> Initializing actions for the surface layer routine. Basically, this involves
724!> the preparation of a lookup table for the the bulk Richardson number vs
725!> Obukhov length L when using the lookup table method.
726!------------------------------------------------------------------------------!
727    SUBROUTINE init_surface_layer_fluxes
728
729       IMPLICIT NONE
730
731
[3685]732       CALL location_message( 'initializing surface layer', .FALSE. )
[1709]733
734!
735!--    In case of runs with neutral statification, set Obukhov length to a
736!--    large value
[2232]737       IF ( neutral )  THEN
738          IF ( surf_def_h(0)%ns >= 1 )  surf_def_h(0)%ol = 1.0E10_wp
739          IF ( surf_lsm_h%ns    >= 1 )  surf_lsm_h%ol    = 1.0E10_wp
740          IF ( surf_usm_h%ns    >= 1 )  surf_usm_h%ol    = 1.0E10_wp
741       ENDIF
[1709]742
[3685]743       CALL location_message( 'finished', .TRUE. )
744
[1691]745    END SUBROUTINE init_surface_layer_fluxes
746
747
748!------------------------------------------------------------------------------!
749! Description:
750! ------------
[1709]751!> Compute the absolute value of the horizontal velocity (relative to the
[2232]752!> surface) for horizontal surface elements. This is required by all methods.
[1691]753!------------------------------------------------------------------------------!
[2232]754    SUBROUTINE calc_uvw_abs
[3157]755   
[1691]756       IMPLICIT NONE
757
[2232]758       INTEGER(iwp) ::  i             !< running index x direction
759       INTEGER(iwp) ::  ibit          !< flag to mask computation of relative velocity in case of downward-facing surfaces
760       INTEGER(iwp) ::  j             !< running index y direction
761       INTEGER(iwp) ::  k             !< running index z direction
762       INTEGER(iwp) ::  m             !< running index surface elements
[1691]763
[3157]764       REAL(wp)     :: w_lfc          !< local free convection velocity scale
[2232]765!
766!--    ibit is 1 for upward-facing surfaces, zero for downward-facing surfaces.
767       ibit = MERGE( 1, 0, .NOT. downward )
[1691]768
[3634]769       !$ACC PARALLEL LOOP PRIVATE(i, j, k, w_lfc) &
770       !$ACC PRESENT(surf, u, v)
[2232]771       DO  m = 1, surf%ns
[1691]772
[2232]773          i   = surf%i(m)           
774          j   = surf%j(m)
775          k   = surf%k(m)
[3157]776       
[1691]777!
[3157]778!--       Calculate free convection velocity scale w_lfc is
779!--       use_free_convection_scaling = .T.. This will maintain a horizontal
780!--       velocity even for very weak wind convective conditions. SIGN is used
781!--       to set w_lfc to zero under stable conditions.
782          IF ( use_free_convection_scaling )  THEN
783             w_lfc = ABS(g / surf%pt1(m) * surf%z_mo(m) * surf%shf(m))
784             w_lfc = ( 0.5_wp * ( w_lfc + SIGN(w_lfc,surf%shf(m)) ) )**(0.33333_wp)
785          ELSE
786             w_lfc = 0.0_wp
787          ENDIF
788
789!
[2232]790!--       Compute the absolute value of the horizontal velocity.
791!--       (relative to the surface in case the lower surface is the ocean).
792!--       Please note, in new surface modelling concept the index values changed,
793!--       i.e. the reference grid point is not the surface-grid point itself but
794!--       the first grid point outside of the topography.
795!--       Note, in case of coupled ocean-atmosphere simulations relative velocity
796!--       with respect to the ocean surface is used, hence, (k-1,j,i) values
797!--       are used to calculate the absolute velocity.
798!--       However, this do not apply for downward-facing walls. To mask this,
799!--       use ibit, which checks for upward/downward-facing surfaces.
800          surf%uvw_abs(m) = SQRT(                                              &
801                              ( 0.5_wp * (   u(k,j,i)   + u(k,j,i+1)           &
802                                        -  ( u(k-1,j,i) + u(k-1,j,i+1)         &
803                                           ) * ibit                            &
804                                         )                                     &
805                              )**2 +                                           &
806                              ( 0.5_wp * (   v(k,j,i)   + v(k,j+1,i)           &
807                                        -  ( v(k-1,j,i) + v(k-1,j+1,i)         &
808                                           ) * ibit                            &
809                                         )                                     &
[3157]810                              )**2  + w_lfc**2                                 &
[2232]811                                )
812
[3148]813                               
814
[1691]815       ENDDO
816
[2232]817    END SUBROUTINE calc_uvw_abs
818
819
820!------------------------------------------------------------------------------!
821! Description:
822! ------------
823!> Compute the absolute value of the horizontal velocity (relative to the
824!> surface) for horizontal surface elements. This is required by all methods.
825!------------------------------------------------------------------------------!
826    SUBROUTINE calc_uvw_abs_v_ugrid
827
828       IMPLICIT NONE
829
[3547]830       INTEGER(iwp) ::  i   !< running index x direction
831       INTEGER(iwp) ::  j   !< running index y direction
832       INTEGER(iwp) ::  k   !< running index z direction
833       INTEGER(iwp) ::  m   !< running index surface elements
[2232]834
[3547]835       REAL(wp)     ::  u_i !< u-component on xu-grid
836       REAL(wp)     ::  w_i !< w-component on xu-grid
[2232]837
838
839       DO  m = 1, surf%ns
840          i   = surf%i(m)           
841          j   = surf%j(m)
842          k   = surf%k(m)
[1691]843!
[2232]844!--       Compute the absolute value of the surface parallel velocity on u-grid.
845          u_i  = u(k,j,i)
846          w_i  = 0.25_wp * ( w(k-1,j,i-1) + w(k-1,j,i) +                       &
847                             w(k,j,i-1)   + w(k,j,i) ) 
[1691]848
[2232]849          surf%uvw_abs(m) = SQRT( u_i**2 + w_i**2 ) 
[1709]850
[2232]851       ENDDO
[1709]852
[2232]853    END SUBROUTINE calc_uvw_abs_v_ugrid
854
[1709]855!------------------------------------------------------------------------------!
856! Description:
857! ------------
[2232]858!> Compute the absolute value of the horizontal velocity (relative to the
859!> surface) for horizontal surface elements. This is required by all methods.
860!------------------------------------------------------------------------------!
861    SUBROUTINE calc_uvw_abs_v_vgrid
862
863       IMPLICIT NONE
864
[3547]865       INTEGER(iwp) ::  i   !< running index x direction
866       INTEGER(iwp) ::  j   !< running index y direction
867       INTEGER(iwp) ::  k   !< running index z direction
868       INTEGER(iwp) ::  m   !< running index surface elements
[2232]869
[3547]870       REAL(wp)     ::  v_i !< v-component on yv-grid
871       REAL(wp)     ::  w_i !< w-component on yv-grid
[2232]872
873
874       DO  m = 1, surf%ns
875          i   = surf%i(m)           
876          j   = surf%j(m)
877          k   = surf%k(m)
878
879          v_i  = u(k,j,i)
880          w_i  = 0.25_wp * ( w(k-1,j-1,i) + w(k-1,j,i) +                       &
881                             w(k,j-1,i)   + w(k,j,i) ) 
882
883          surf%uvw_abs(m) = SQRT( v_i**2 + w_i**2 ) 
884
885       ENDDO
886
887    END SUBROUTINE calc_uvw_abs_v_vgrid
888
889!------------------------------------------------------------------------------!
890! Description:
891! ------------
892!> Compute the absolute value of the horizontal velocity (relative to the
893!> surface) for horizontal surface elements. This is required by all methods.
894!------------------------------------------------------------------------------!
895    SUBROUTINE calc_uvw_abs_v_wgrid
896
897       IMPLICIT NONE
898
[3547]899       INTEGER(iwp) ::  i   !< running index x direction
900       INTEGER(iwp) ::  j   !< running index y direction
901       INTEGER(iwp) ::  k   !< running index z direction
902       INTEGER(iwp) ::  m   !< running index surface elements
[2232]903
[3547]904       REAL(wp)     ::  u_i !< u-component on x-zw-grid
905       REAL(wp)     ::  v_i !< v-component on y-zw-grid
906       REAL(wp)     ::  w_i !< w-component on zw-grid
[2232]907!
908!--    North- (l=0) and south-facing (l=1) surfaces
909       IF ( l == 0  .OR.  l == 1 )  THEN
910          DO  m = 1, surf%ns
911             i   = surf%i(m)           
912             j   = surf%j(m)
913             k   = surf%k(m)
914
915             u_i  = 0.25_wp * ( u(k+1,j,i+1) + u(k+1,j,i) +                    &
916                                u(k,j,i+1)   + u(k,j,i) )
917             v_i  = 0.0_wp
918             w_i  = w(k,j,i)
919
920             surf%uvw_abs(m) = SQRT( u_i**2 + v_i**2 + w_i**2 ) 
921          ENDDO
922!
923!--    East- (l=2) and west-facing (l=3) surfaces
924       ELSE
925          DO  m = 1, surf%ns
926             i   = surf%i(m)           
927             j   = surf%j(m)
928             k   = surf%k(m)
929
930             u_i  = 0.0_wp
931             v_i  = 0.25_wp * ( v(k+1,j+1,i) + v(k+1,j,i) +                    &
932                                v(k,j+1,i)   + v(k,j,i) )
933             w_i  = w(k,j,i)
934
935             surf%uvw_abs(m) = SQRT( u_i**2 + v_i**2 + w_i**2 ) 
936          ENDDO
937       ENDIF           
938
939    END SUBROUTINE calc_uvw_abs_v_wgrid
940
941!------------------------------------------------------------------------------!
942! Description:
943! ------------
944!> Compute the absolute value of the horizontal velocity (relative to the
945!> surface) for horizontal surface elements. This is required by all methods.
946!------------------------------------------------------------------------------!
947    SUBROUTINE calc_uvw_abs_v_sgrid
948
949       IMPLICIT NONE
950
[3547]951       INTEGER(iwp) ::  i   !< running index x direction
952       INTEGER(iwp) ::  j   !< running index y direction
953       INTEGER(iwp) ::  k   !< running index z direction
954       INTEGER(iwp) ::  m   !< running index surface elements
[2232]955
[3547]956       REAL(wp)     ::  u_i !< u-component on scalar grid
957       REAL(wp)     ::  v_i !< v-component on scalar grid
958       REAL(wp)     ::  w_i !< w-component on scalar grid
[2232]959
960!
961!--    North- (l=0) and south-facing (l=1) walls
962       IF ( l == 0  .OR.  l == 1 )  THEN
963          DO  m = 1, surf%ns
964             i   = surf%i(m)           
965             j   = surf%j(m)
966             k   = surf%k(m)
967
968             u_i = 0.5_wp * ( u(k,j,i) + u(k,j,i+1) )
969             v_i = 0.0_wp
970             w_i = 0.5_wp * ( w(k,j,i) + w(k-1,j,i) )
971
972             surf%uvw_abs(m) = SQRT( u_i**2 + v_i**2 + w_i**2 ) 
973          ENDDO
974!
975!--    East- (l=2) and west-facing (l=3) walls
976       ELSE
977          DO  m = 1, surf%ns
978             i   = surf%i(m)           
979             j   = surf%j(m)
980             k   = surf%k(m)
981
982             u_i = 0.0_wp
983             v_i = 0.5_wp * ( v(k,j,i) + v(k,j+1,i) )
984             w_i = 0.5_wp * ( w(k,j,i) + w(k-1,j,i) )
985
986             surf%uvw_abs(m) = SQRT( u_i**2 + v_i**2 + w_i**2 ) 
987          ENDDO
988       ENDIF 
989
990    END SUBROUTINE calc_uvw_abs_v_sgrid
991
992
993!------------------------------------------------------------------------------!
994! Description:
995! ------------
[1709]996!> Calculate the Obukhov length (L) and Richardson flux number (z/L)
997!------------------------------------------------------------------------------!
998    SUBROUTINE calc_ol
999
1000       IMPLICIT NONE
1001
[2232]1002       INTEGER(iwp) ::  iter    !< Newton iteration step
1003       INTEGER(iwp) ::  m       !< loop variable over all horizontal wall elements
[1709]1004
1005       REAL(wp)     :: f,      & !< Function for Newton iteration: f = Ri - [...]/[...]^2 = 0
1006                       f_d_ol, & !< Derivative of f
1007                       ol_l,   & !< Lower bound of L for Newton iteration
1008                       ol_m,   & !< Previous value of L for Newton iteration
1009                       ol_old, & !< Previous time step value of L
1010                       ol_u      !< Upper bound of L for Newton iteration
1011
[2232]1012!
[3668]1013!--    Evaluate bulk Richardson number (calculation depends on
1014!--    definition based on setting of boundary conditions
1015       IF ( ibc_pt_b /= 1 )  THEN
1016          IF ( humidity )  THEN
1017             !$OMP PARALLEL DO PRIVATE( z_mo )
1018             DO  m = 1, surf%ns
[1691]1019
[3668]1020                z_mo = surf%z_mo(m)
[2232]1021
[3668]1022                surf%rib(m) = g * z_mo                                         &
1023                              * ( surf%vpt1(m) - surf%vpt_surface(m) )         &
1024                              / ( surf%uvw_abs(m)**2 * surf%vpt1(m)            &
1025                              + 1.0E-20_wp )
1026             ENDDO
1027          ELSE
1028             !$OMP PARALLEL DO PRIVATE( z_mo )
1029             DO  m = 1, surf%ns
[2232]1030
[3668]1031                z_mo = surf%z_mo(m)
[2232]1032
[3668]1033                surf%rib(m) = g * z_mo                                         &
1034                              * ( surf%pt1(m) - surf%pt_surface(m) )           &
1035                              / ( surf%uvw_abs(m)**2 * surf%pt1(m) + 1.0E-20_wp )
1036             ENDDO
1037          ENDIF
1038       ELSE
1039          IF ( humidity )  THEN
1040             !$OMP PARALLEL DO PRIVATE( k, z_mo )
1041             DO  m = 1, surf%ns
[2232]1042
[3668]1043                k   = surf%k(m)
[2232]1044
[3668]1045                z_mo = surf%z_mo(m)
[2232]1046
[3668]1047                surf%rib(m) = - g * z_mo * ( ( 1.0_wp + 0.61_wp                &
[3146]1048                           * surf%qv1(m) ) * surf%shf(m) + 0.61_wp             &
1049                           * surf%pt1(m) * surf%qsws(m) ) *                    &
[2232]1050                             drho_air_zw(k-1)                /                 &
[3146]1051                         ( surf%uvw_abs(m)**3 * surf%vpt1(m) * kappa**2        &
[1709]1052                           + 1.0E-20_wp )
[3668]1053             ENDDO
1054          ELSE
1055             !$OMP PARALLEL DO PRIVATE( k, z_mo )
1056             !$ACC PARALLEL LOOP PRIVATE(k, z_mo) &
1057             !$ACC PRESENT(surf, drho_air_zw)
1058             DO  m = 1, surf%ns
[1691]1059
[3668]1060                k   = surf%k(m)
[2232]1061
[3668]1062                z_mo = surf%z_mo(m)
[2232]1063
[3668]1064                surf%rib(m) = - g * z_mo * surf%shf(m) *                    &
1065                                     drho_air_zw(k-1)            /          &
1066                        ( surf%uvw_abs(m)**3 * surf%pt1(m) * kappa**2       &
1067                        + 1.0E-20_wp )
1068             ENDDO
[2232]1069          ENDIF
[1691]1070       ENDIF
1071
1072!
[3668]1073!--    Calculate the Obukhov length using Newton iteration
1074       !$ACC PARALLEL LOOP PRIVATE(i, j, z_mo) &
1075       !$ACC PRIVATE(ol_old, ol_m, ol_l, ol_u, f, f_d_ol) &
1076       !$ACC PRESENT(surf)
1077       DO  m = 1, surf%ns
[1691]1078
[3668]1079          i   = surf%i(m)           
1080          j   = surf%j(m)
[1691]1081
[3668]1082          z_mo = surf%z_mo(m)
[1691]1083
1084!
[3668]1085!--       Store current value in case the Newton iteration fails
1086          ol_old = surf%ol(m)
[1691]1087
1088!
[3668]1089!--       Ensure that the bulk Richardson number and the Obukhov
1090!--       length have the same sign
1091          IF ( surf%rib(m) * surf%ol(m) < 0.0_wp  .OR.                      &
1092               ABS( surf%ol(m) ) == ol_max )  THEN
1093             IF ( surf%rib(m) > 1.0_wp ) surf%ol(m) =  0.01_wp
1094             IF ( surf%rib(m) < 0.0_wp ) surf%ol(m) = -0.01_wp
1095          ENDIF
[1691]1096!
[3668]1097!--       Iteration to find Obukhov length
1098          iter = 0
1099          DO
1100             iter = iter + 1
[1691]1101!
[3668]1102!--          In case of divergence, use the value of the previous time step
1103             IF ( iter > 1000 )  THEN
1104                surf%ol(m) = ol_old
1105                EXIT
1106             ENDIF
[1691]1107
[3668]1108             ol_m = surf%ol(m)
1109             ol_l = ol_m - 0.001_wp * ol_m
1110             ol_u = ol_m + 0.001_wp * ol_m
[1691]1111
1112
[3668]1113             IF ( ibc_pt_b /= 1 )  THEN
[1691]1114!
[3668]1115!--             Calculate f = Ri - [...]/[...]^2 = 0
1116                f = surf%rib(m) - ( z_mo / ol_m ) * (                          &
1117                                              LOG( z_mo / surf%z0h(m) )        &
1118                                              - psi_h( z_mo / ol_m )           &
1119                                              + psi_h( surf%z0h(m) /           &
1120                                                       ol_m )                  & 
1121                                                     )                         &
1122                                           / ( LOG( z_mo / surf%z0(m) )        &
1123                                              - psi_m( z_mo / ol_m )           &
1124                                              + psi_m( surf%z0(m) /  ol_m )    &
[2232]1125                                                 )**2
[1691]1126
1127!
[3668]1128!--              Calculate df/dL
1129                 f_d_ol = ( - ( z_mo / ol_u ) * ( LOG( z_mo /                  &
1130                                                          surf%z0h(m) )        &
1131                                         - psi_h( z_mo / ol_u )                &
1132                                         + psi_h( surf%z0h(m) / ol_u )         &
1133                                           )                                   &
1134                                         / ( LOG( z_mo / surf%z0(m) )          &
1135                                         - psi_m( z_mo / ol_u )                &
1136                                         + psi_m( surf%z0(m) / ol_u )          &
1137                                           )**2                                &
1138                        + ( z_mo / ol_l ) * ( LOG( z_mo / surf%z0h(m) )        &
1139                                         - psi_h( z_mo / ol_l )                &
1140                                         + psi_h( surf%z0h(m) / ol_l )         &
1141                                           )                                   &
1142                                         / ( LOG( z_mo / surf%z0(m) )          &
1143                                         - psi_m( z_mo / ol_l )                &
1144                                         + psi_m( surf%z0(m) / ol_l )          &
1145                                           )**2                                &
1146                          ) / ( ol_u - ol_l )
1147             ELSE
[1691]1148!
[3668]1149!--             Calculate f = Ri - 1 /[...]^3 = 0
1150                f = surf%rib(m) - ( z_mo / ol_m ) /                            &
1151                                             ( LOG( z_mo / surf%z0(m) )        &
1152                                         - psi_m( z_mo / ol_m )                &
1153                                         + psi_m( surf%z0(m) / ol_m )          &
1154                                             )**3
[1691]1155
1156!
[3668]1157!--             Calculate df/dL
1158                f_d_ol = ( - ( z_mo / ol_u ) / ( LOG( z_mo / surf%z0(m) )      &
1159                                         - psi_m( z_mo / ol_u )                &
1160                                         + psi_m( surf%z0(m) / ol_u )          &
1161                                                  )**3                         &
[2232]1162                           + ( z_mo / ol_l ) / ( LOG( z_mo / surf%z0(m) )      &
[3668]1163                                         - psi_m( z_mo / ol_l )                &
1164                                         + psi_m( surf%z0(m) / ol_l )          &
1165                                            )**3                               &
1166                          ) / ( ol_u - ol_l )
1167             ENDIF
[1691]1168!
[3668]1169!--          Calculate new L
1170             surf%ol(m) = ol_m - f / f_d_ol
[1691]1171
1172!
[3668]1173!--          Ensure that the bulk Richardson number and the Obukhov
1174!--          length have the same sign and ensure convergence.
1175             IF ( surf%ol(m) * ol_m < 0.0_wp )  surf%ol(m) = ol_m * 0.5_wp
[1691]1176!
[3668]1177!--          If unrealistic value occurs, set L to the maximum
1178!--          value that is allowed
1179             IF ( ABS( surf%ol(m) ) > ol_max )  THEN
1180                surf%ol(m) = ol_max
1181                EXIT
1182             ENDIF
[1691]1183!
[3668]1184!--          Check for convergence
1185             IF ( ABS( ( surf%ol(m) - ol_m ) /  surf%ol(m) ) < 1.0E-4_wp )  THEN
1186                EXIT
[2232]1187             ELSE
[3668]1188                CYCLE
[2232]1189             ENDIF
[1691]1190
1191          ENDDO
[3668]1192       ENDDO
[1691]1193
1194    END SUBROUTINE calc_ol
1195
1196!
1197!-- Calculate friction velocity u*
1198    SUBROUTINE calc_us
1199
1200       IMPLICIT NONE
1201
[2232]1202       INTEGER(iwp) ::  m       !< loop variable over all horizontal surf elements
[1691]1203
[2232]1204!
1205!--    Compute u* at horizontal surfaces at the scalars' grid points
1206       IF ( .NOT. surf_vertical )  THEN
1207!
1208!--       Compute u* at upward-facing surfaces
1209          IF ( .NOT. downward )  THEN
[2281]1210             !$OMP PARALLEL  DO PRIVATE( z_mo )
[3634]1211             !$ACC PARALLEL LOOP PRIVATE(z_mo) &
1212             !$ACC PRESENT(surf)
[2232]1213             DO  m = 1, surf%ns
[1691]1214
[2232]1215                z_mo = surf%z_mo(m)
[1691]1216!
[2232]1217!--             Compute u* at the scalars' grid points
1218                surf%us(m) = kappa * surf%uvw_abs(m) /                         &
1219                            ( LOG( z_mo / surf%z0(m) )                         &
1220                           - psi_m( z_mo / surf%ol(m) )                        &
1221                           + psi_m( surf%z0(m) / surf%ol(m) ) )
1222   
1223             ENDDO
1224!
1225!--       Compute u* at downward-facing surfaces. This case, do not consider
1226!--       any stability.
1227          ELSE
[2281]1228             !$OMP PARALLEL  DO PRIVATE( z_mo )
[3634]1229             !$ACC PARALLEL LOOP PRIVATE(z_mo) &
1230             !$ACC PRESENT(surf)
[2232]1231             DO  m = 1, surf%ns
1232
1233                z_mo = surf%z_mo(m)
1234!
1235!--             Compute u* at the scalars' grid points
1236                surf%us(m) = kappa * surf%uvw_abs(m) / LOG( z_mo / surf%z0(m) )
1237   
1238             ENDDO
1239          ENDIF
1240!
1241!--    Compute u* at vertical surfaces at the u/v/v grid, respectively.
1242!--    No stability is considered in this case.
1243       ELSE
1244          !$OMP PARALLEL DO PRIVATE( z_mo )
[3634]1245          !$ACC PARALLEL LOOP PRIVATE(z_mo) &
1246          !$ACC PRESENT(surf)
[2232]1247          DO  m = 1, surf%ns
1248             z_mo = surf%z_mo(m)
1249
1250             surf%us(m) = kappa * surf%uvw_abs(m) / LOG( z_mo / surf%z0(m) )
[1691]1251          ENDDO
[2232]1252       ENDIF
[1691]1253
1254    END SUBROUTINE calc_us
1255
1256!
[3146]1257!-- Calculate potential temperature, specific humidity, and virtual potential
1258!-- temperature at first grid level
[1691]1259    SUBROUTINE calc_pt_q
1260
1261       IMPLICIT NONE
1262
[2232]1263       INTEGER(iwp) ::  m       !< loop variable over all horizontal surf elements
1264
1265       !$OMP PARALLEL DO PRIVATE( i, j, k )
[3634]1266       !$ACC PARALLEL LOOP PRIVATE(i, j, k) &
1267       !$ACC PRESENT(surf, pt)
[2232]1268       DO  m = 1, surf%ns 
1269
1270          i   = surf%i(m)           
1271          j   = surf%j(m)
1272          k   = surf%k(m)
1273
[3634]1274#ifndef _OPENACC
[3274]1275          IF ( bulk_cloud_model ) THEN
1276             surf%pt1(m) = pt(k,j,i) + lv_d_cp * d_exner(k) * ql(k,j,i)
[2547]1277             surf%qv1(m) = q(k,j,i) - ql(k,j,i)
1278          ELSEIF( cloud_droplets ) THEN
[3274]1279             surf%pt1(m) = pt(k,j,i) + lv_d_cp * d_exner(k) * ql(k,j,i)
[2547]1280             surf%qv1(m) = q(k,j,i) 
[2696]1281          ELSE
[3634]1282#endif
[2696]1283             surf%pt1(m) = pt(k,j,i)
[3634]1284#ifndef _OPENACC
[2696]1285             IF ( humidity )  THEN
1286                surf%qv1(m) = q(k,j,i)
1287             ELSE
[3634]1288#endif
[2696]1289                surf%qv1(m) = 0.0_wp
[3634]1290#ifndef _OPENACC
[2696]1291             ENDIF
[2547]1292          ENDIF
[2232]1293
[3146]1294          IF ( humidity )  THEN
1295             surf%vpt1(m) = pt(k,j,i) * ( 1.0_wp + 0.61_wp * q(k,j,i) )
1296          ENDIF
[3634]1297#endif
[3146]1298         
[1691]1299       ENDDO
1300
1301    END SUBROUTINE calc_pt_q
1302
[2696]1303
[1691]1304!
[3152]1305!-- Set potential temperature at surface grid level.
[2696]1306!-- ( only for upward-facing surfs )
1307    SUBROUTINE calc_pt_surface
1308
1309       IMPLICIT NONE
1310
[3146]1311       INTEGER(iwp) ::  k_off    !< index offset between surface and atmosphere grid point (-1 for upward-, +1 for downward-facing walls)
[2696]1312       INTEGER(iwp) ::  m       !< loop variable over all horizontal surf elements
1313       
[3146]1314       k_off = surf%koff
[2696]1315       !$OMP PARALLEL DO PRIVATE( i, j, k )
[3634]1316       !$ACC PARALLEL LOOP PRIVATE(i, j, k) &
1317       !$ACC PRESENT(surf, pt)
[2696]1318       DO  m = 1, surf%ns 
1319
1320          i   = surf%i(m)           
1321          j   = surf%j(m)
1322          k   = surf%k(m)
1323
[3146]1324          surf%pt_surface(m) = pt(k+k_off,j,i)
[2696]1325
1326       ENDDO
1327
1328    END SUBROUTINE calc_pt_surface
1329
1330!
[3152]1331!-- Set mixing ratio at surface grid level. ( Only for upward-facing surfs. )
1332    SUBROUTINE calc_q_surface
1333
1334       IMPLICIT NONE
1335
1336       INTEGER(iwp) ::  k_off   !< index offset between surface and atmosphere grid point (-1 for upward-, +1 for downward-facing walls)
1337       INTEGER(iwp) ::  m       !< loop variable over all horizontal surf elements
1338       
1339       k_off = surf%koff
1340       !$OMP PARALLEL DO PRIVATE( i, j, k )
1341       DO  m = 1, surf%ns 
1342
1343          i   = surf%i(m)           
1344          j   = surf%j(m)
1345          k   = surf%k(m)
1346
1347          surf%q_surface(m) = q(k+k_off,j,i)
1348
1349       ENDDO
1350
1351    END SUBROUTINE calc_q_surface
1352   
1353!
1354!-- Set virtual potential temperature at surface grid level.
[3146]1355!-- ( only for upward-facing surfs )
1356    SUBROUTINE calc_vpt_surface
1357
1358       IMPLICIT NONE
1359
1360       INTEGER(iwp) ::  k_off    !< index offset between surface and atmosphere grid point (-1 for upward-, +1 for downward-facing walls)
1361       INTEGER(iwp) ::  m       !< loop variable over all horizontal surf elements
1362       
1363       k_off = surf%koff
1364       !$OMP PARALLEL DO PRIVATE( i, j, k )
1365       DO  m = 1, surf%ns 
1366
1367          i   = surf%i(m)           
1368          j   = surf%j(m)
1369          k   = surf%k(m)
1370
1371          surf%vpt_surface(m) = vpt(k+k_off,j,i)
1372
1373       ENDDO
1374
1375    END SUBROUTINE calc_vpt_surface
1376   
1377!
[2292]1378!-- Calculate the other MOST scaling parameters theta*, q*, (qc*, qr*, nc*, nr*)
[1691]1379    SUBROUTINE calc_scaling_parameters
1380
1381       IMPLICIT NONE
1382
[2232]1383
1384       INTEGER(iwp)  ::  m       !< loop variable over all horizontal surf elements
[2696]1385       INTEGER(iwp)  ::  lsp     !< running index for chemical species
[1691]1386!
[2232]1387!--    Compute theta* at horizontal surfaces
1388       IF ( constant_heatflux  .AND.  .NOT. surf_vertical )  THEN
[1691]1389!
1390!--       For a given heat flux in the surface layer:
[2232]1391
1392          !$OMP PARALLEL DO PRIVATE( i, j, k )
[3634]1393          !$ACC PARALLEL LOOP PRIVATE(i, j, k) &
1394          !$ACC PRESENT(surf, drho_air_zw)
[2232]1395          DO  m = 1, surf%ns 
1396
1397             i   = surf%i(m)           
1398             j   = surf%j(m)
1399             k   = surf%k(m)
1400
1401             surf%ts(m) = -surf%shf(m) * drho_air_zw(k-1) /                    &
1402                                  ( surf%us(m) + 1E-30_wp )
1403
[1691]1404!
[2232]1405!--          ts must be limited, because otherwise overflow may occur in case
1406!--          of us=0 when computing ol further below
1407             IF ( surf%ts(m) < -1.05E5_wp )  surf%ts(m) = -1.0E5_wp
1408             IF ( surf%ts(m) >  1.0E5_wp  )  surf%ts(m) =  1.0E5_wp
1409
[1691]1410          ENDDO
1411
[2232]1412       ELSEIF ( .NOT. surf_vertical ) THEN
[1691]1413!
1414!--       For a given surface temperature:
[1788]1415          IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
[2232]1416
1417             !$OMP PARALLEL DO PRIVATE( i, j, k )
1418             DO  m = 1, surf%ns 
1419                i   = surf%i(m)           
1420                j   = surf%j(m)
1421                k   = surf%k(m)
1422
1423                pt(k-1,j,i) = pt_surface
[1691]1424             ENDDO
1425          ENDIF
1426
[2696]1427          !$OMP PARALLEL DO PRIVATE( z_mo )
1428          DO  m = 1, surf%ns   
[1691]1429
[2696]1430             z_mo = surf%z_mo(m)
[1691]1431
[2696]1432             surf%ts(m) = kappa * ( surf%pt1(m) - surf%pt_surface(m) )      &
1433                                  / ( LOG( z_mo / surf%z0h(m) )             &
1434                                      - psi_h( z_mo / surf%ol(m) )          &
1435                                      + psi_h( surf%z0h(m) / surf%ol(m) ) )
[1691]1436
[2696]1437          ENDDO
[2232]1438
1439       ENDIF
1440!
1441!--    Compute theta* at vertical surfaces. This is only required in case of
1442!--    land-surface model, in order to compute aerodynamical resistance.
1443       IF ( surf_vertical )  THEN
[2281]1444          !$OMP PARALLEL DO PRIVATE( i, j )
[2232]1445          DO  m = 1, surf%ns 
1446
1447             i          =  surf%i(m)           
1448             j          =  surf%j(m)
1449             surf%ts(m) = -surf%shf(m) / ( surf%us(m) + 1E-30_wp )
1450!
1451!--          ts must be limited, because otherwise overflow may occur in case
1452!--          of us=0 when computing ol further below
1453             IF ( surf%ts(m) < -1.05E5_wp )  surf%ts(m) = -1.0E5_wp
1454             IF ( surf%ts(m) >  1.0E5_wp  )  surf%ts(m) =  1.0E5_wp
1455
[1691]1456          ENDDO
1457       ENDIF
1458
1459!
[2232]1460!--    If required compute q* at horizontal surfaces
[1960]1461       IF ( humidity )  THEN
[2232]1462          IF ( constant_waterflux  .AND.  .NOT. surf_vertical )  THEN
[1691]1463!
[1788]1464!--          For a given water flux in the surface layer
[2232]1465             !$OMP PARALLEL DO PRIVATE( i, j, k )
1466             DO  m = 1, surf%ns 
1467
1468                i   = surf%i(m)           
1469                j   = surf%j(m)
1470                k   = surf%k(m)
1471                surf%qs(m) = -surf%qsws(m) * drho_air_zw(k-1) /                &
1472                                               ( surf%us(m) + 1E-30_wp )
1473
[1691]1474             ENDDO
1475
[2232]1476          ELSEIF ( .NOT. surf_vertical )  THEN
[1788]1477             coupled_run = ( coupling_mode == 'atmosphere_to_ocean'  .AND.     &
[1691]1478                             run_coupled )
1479
[1788]1480             IF ( large_scale_forcing  .AND.  lsf_surf )  THEN
[2232]1481                !$OMP PARALLEL DO PRIVATE( i, j, k )
1482                DO  m = 1, surf%ns 
1483
1484                   i   = surf%i(m)           
1485                   j   = surf%j(m)
1486                   k   = surf%k(m)
1487                   q(k-1,j,i) = q_surface
1488                   
[1691]1489                ENDDO
1490             ENDIF
1491
1492!
[2232]1493!--          Assume saturation for atmosphere coupled to ocean (but not
1494!--          in case of precursor runs)
1495             IF ( coupled_run )  THEN
1496                !$OMP PARALLEL DO PRIVATE( i, j, k, e_s )
1497                DO  m = 1, surf%ns   
1498                   i   = surf%i(m)           
1499                   j   = surf%j(m)
1500                   k   = surf%k(m)
1501                   e_s = 6.1_wp * &
1502                              EXP( 0.07_wp * ( MIN(pt(k-1,j,i),pt(k,j,i))      &
[1691]1503                                               - 273.15_wp ) )
[3361]1504                   q(k-1,j,i) = rd_d_rv * e_s / ( surface_pressure - e_s )
[2232]1505                ENDDO
1506             ENDIF
[1691]1507
[3274]1508             IF ( bulk_cloud_model  .OR.  cloud_droplets )  THEN
[2232]1509               !$OMP PARALLEL DO PRIVATE( i, j, k, z_mo )
1510                DO  m = 1, surf%ns   
[1691]1511
[2232]1512                   i   = surf%i(m)           
1513                   j   = surf%j(m)
1514                   k   = surf%k(m)
1515   
1516                   z_mo = surf%z_mo(m)
[1691]1517
[3152]1518                   surf%qs(m) = kappa * ( surf%qv1(m) - surf%q_surface(m) )    &
[2232]1519                                        / ( LOG( z_mo / surf%z0q(m) )          &
1520                                            - psi_h( z_mo / surf%ol(m) )       &
1521                                            + psi_h( surf%z0q(m) /             &
1522                                                     surf%ol(m) ) )
[1691]1523                ENDDO
[2232]1524             ELSE
1525                !$OMP PARALLEL DO PRIVATE( i, j, k, z_mo )
1526                DO  m = 1, surf%ns   
1527
1528                   i   = surf%i(m)           
1529                   j   = surf%j(m)
1530                   k   = surf%k(m)
1531   
1532                   z_mo = surf%z_mo(m)
1533
1534                   surf%qs(m) = kappa * ( q(k,j,i) - q(k-1,j,i) )              &
1535                                        / ( LOG( z_mo / surf%z0q(m) )          &
1536                                            - psi_h( z_mo / surf%ol(m) )       &
1537                                            + psi_h( surf%z0q(m) /             &
1538                                                     surf%ol(m) ) )
1539                ENDDO
1540             ENDIF
1541          ENDIF
1542!
1543!--       Compute q* at vertical surfaces
1544          IF ( surf_vertical )  THEN
[2281]1545             !$OMP PARALLEL DO PRIVATE( i, j )
[2232]1546             DO  m = 1, surf%ns 
1547
1548                i          =  surf%i(m)           
1549                j          =  surf%j(m)
1550                surf%qs(m) = -surf%qsws(m) / ( surf%us(m) + 1E-30_wp )
1551
[1691]1552             ENDDO
1553          ENDIF
1554       ENDIF
[1960]1555       
1556!
1557!--    If required compute s*
1558       IF ( passive_scalar )  THEN
1559!
[2232]1560!--       At horizontal surfaces
1561          IF ( constant_scalarflux  .AND.  .NOT. surf_vertical )  THEN
1562!
1563!--          For a given scalar flux in the surface layer
[2281]1564             !$OMP PARALLEL DO PRIVATE( i, j )
[2232]1565             DO  m = 1, surf%ns 
1566                i   = surf%i(m)           
1567                j   = surf%j(m)
1568                surf%ss(m) = -surf%ssws(m) / ( surf%us(m) + 1E-30_wp )
[1960]1569             ENDDO
1570          ENDIF
[2232]1571!
1572!--       At vertical surfaces
1573          IF ( surf_vertical )  THEN
[2281]1574             !$OMP PARALLEL DO PRIVATE( i, j )
[2232]1575             DO  m = 1, surf%ns 
1576                i          =  surf%i(m)           
1577                j          =  surf%j(m)
1578                surf%ss(m) = -surf%ssws(m) / ( surf%us(m) + 1E-30_wp )
1579             ENDDO
1580          ENDIF
[1960]1581       ENDIF
[1691]1582
[2292]1583!
[2696]1584!--    If required compute cs* (chemical species)
1585       IF ( air_chemistry  )  THEN 
1586!
1587!--       At horizontal surfaces                             
1588          DO  lsp = 1, nvar
1589             IF ( constant_csflux(lsp)  .AND.  .NOT.  surf_vertical )  THEN
1590!--             For a given chemical species' flux in the surface layer
1591                !$OMP PARALLEL DO PRIVATE( i, j )
1592                DO  m = 1, surf%ns 
1593                   i   = surf%i(m)           
1594                   j   = surf%j(m)
1595                   surf%css(lsp,m) = -surf%cssws(lsp,m) / ( surf%us(m) + 1E-30_wp )
1596                ENDDO
1597             ENDIF
1598          ENDDO
1599!
1600!--       At vertical surfaces
1601          IF ( surf_vertical )  THEN
1602             DO  lsp = 1, nvar
1603                !$OMP PARALLEL DO PRIVATE( i, j )
1604                DO  m = 1, surf%ns 
1605                   i   = surf%i(m)           
1606                   j   = surf%j(m)
1607                   surf%css(lsp,m) = -surf%cssws(lsp,m) / ( surf%us(m) + 1E-30_wp )
1608                ENDDO
1609             ENDDO
1610          ENDIF
1611       ENDIF
1612
1613!
[2292]1614!--    If required compute qc* and nc*
[3274]1615       IF ( bulk_cloud_model  .AND.  microphysics_morrison  .AND.              &
[2292]1616            .NOT. surf_vertical )  THEN
1617          !$OMP PARALLEL DO PRIVATE( i, j, k, z_mo )
1618          DO  m = 1, surf%ns   
[1691]1619
[2292]1620             i    = surf%i(m)           
1621             j    = surf%j(m)
1622             k    = surf%k(m)
1623
1624             z_mo = surf%z_mo(m)
1625
1626             surf%qcs(m) = kappa * ( qc(k,j,i) - qc(k-1,j,i) )                 &
1627                                 / ( LOG( z_mo / surf%z0q(m) )                 &
1628                                 - psi_h( z_mo / surf%ol(m) )                  &
1629                                 + psi_h( surf%z0q(m) / surf%ol(m) ) )
1630
1631             surf%ncs(m) = kappa * ( nc(k,j,i) - nc(k-1,j,i) )                 &
1632                                 / ( LOG( z_mo / surf%z0q(m) )                 &
1633                                 - psi_h( z_mo / surf%ol(m) )                  &
1634                                 + psi_h( surf%z0q(m) / surf%ol(m) ) )
1635          ENDDO
1636
1637       ENDIF
1638
[1691]1639!
1640!--    If required compute qr* and nr*
[3274]1641       IF ( bulk_cloud_model  .AND.  microphysics_seifert  .AND.               &
[2232]1642            .NOT. surf_vertical )  THEN
1643          !$OMP PARALLEL DO PRIVATE( i, j, k, z_mo )
1644          DO  m = 1, surf%ns   
[1691]1645
[2232]1646             i    = surf%i(m)           
1647             j    = surf%j(m)
1648             k    = surf%k(m)
[1691]1649
[2232]1650             z_mo = surf%z_mo(m)
[1691]1651
[2232]1652             surf%qrs(m) = kappa * ( qr(k,j,i) - qr(k-1,j,i) )                 &
1653                                 / ( LOG( z_mo / surf%z0q(m) )                 &
1654                                 - psi_h( z_mo / surf%ol(m) )                  &
1655                                 + psi_h( surf%z0q(m) / surf%ol(m) ) )
[1691]1656
[2232]1657             surf%nrs(m) = kappa * ( nr(k,j,i) - nr(k-1,j,i) )                 &
1658                                 / ( LOG( z_mo / surf%z0q(m) )                 &
1659                                 - psi_h( z_mo / surf%ol(m) )                  &
1660                                 + psi_h( surf%z0q(m) / surf%ol(m) ) )
[1691]1661          ENDDO
1662
1663       ENDIF
1664
1665    END SUBROUTINE calc_scaling_parameters
1666
1667
1668
1669!
[2292]1670!-- Calculate surface fluxes usws, vsws, shf, qsws, (qcsws, qrsws, ncsws, nrsws)
[1691]1671    SUBROUTINE calc_surface_fluxes
1672
1673       IMPLICIT NONE
1674
[2696]1675       INTEGER(iwp)  ::  m       !< loop variable over all horizontal surf elements
1676       INTEGER(iwp)  ::  lsp     !< running index for chemical species
[1691]1677
[2232]1678       REAL(wp)                            ::  dum     !< dummy to precalculate logarithm
1679       REAL(wp)                            ::  flag_u  !< flag indicating u-grid, used for calculation of horizontal momentum fluxes at vertical surfaces
1680       REAL(wp)                            ::  flag_v  !< flag indicating v-grid, used for calculation of horizontal momentum fluxes at vertical surfaces
1681       REAL(wp), DIMENSION(:), ALLOCATABLE ::  u_i     !< u-component interpolated onto scalar grid point, required for momentum fluxes at vertical surfaces
1682       REAL(wp), DIMENSION(:), ALLOCATABLE ::  v_i     !< v-component interpolated onto scalar grid point, required for momentum fluxes at vertical surfaces
1683       REAL(wp), DIMENSION(:), ALLOCATABLE ::  w_i     !< w-component interpolated onto scalar grid point, required for momentum fluxes at vertical surfaces
[1691]1684
1685!
[2232]1686!--    Calcuate surface fluxes at horizontal walls
1687       IF ( .NOT. surf_vertical )  THEN
1688!
1689!--       Compute u'w' for the total model domain at upward-facing surfaces.
1690!--       First compute the corresponding component of u* and square it.
1691          IF ( .NOT. downward )  THEN
1692             !$OMP PARALLEL DO PRIVATE( i, j, k, z_mo )
[3634]1693             !$ACC PARALLEL LOOP PRIVATE(i, j, k, z_mo) &
1694             !$ACC PRESENT(surf, u, rho_air_zw)
[2232]1695             DO  m = 1, surf%ns 
1696   
1697                i = surf%i(m)           
1698                j = surf%j(m)
1699                k = surf%k(m)
[1691]1700
[2232]1701                z_mo = surf%z_mo(m)
[1691]1702
[2232]1703                surf%usws(m) = kappa * ( u(k,j,i) - u(k-1,j,i) )               &
1704                              / ( LOG( z_mo / surf%z0(m) )                     &
1705                                  - psi_m( z_mo / surf%ol(m) )                 &
1706                                  + psi_m( surf%z0(m) / surf%ol(m) ) )
1707!
1708!--             Please note, the computation of usws is not fully accurate. Actually
1709!--             a further interpolation of us onto the u-grid, where usws is defined,
1710!--             is required. However, this is not done as this would require several
1711!--             data transfers between 2D-grid and the surf-type.
1712!--             The impact of the missing interpolation is negligible as several
1713!--             tests had shown.
1714!--             Same also for ol. 
1715                surf%usws(m) = -surf%usws(m) * surf%us(m) * rho_air_zw(k-1)
[1691]1716
[2232]1717             ENDDO
[1691]1718!
[2232]1719!--       At downward-facing surfaces
1720          ELSE
1721             !$OMP PARALLEL DO PRIVATE( i, j, k, z_mo )
1722             DO  m = 1, surf%ns 
1723   
1724                i = surf%i(m)           
1725                j = surf%j(m)
1726                k = surf%k(m)
[1691]1727
[2232]1728                z_mo = surf%z_mo(m)
1729
1730                surf%usws(m) = kappa * u(k,j,i) / LOG( z_mo / surf%z0(m) )
1731                surf%usws(m) = surf%usws(m) * surf%us(m) * rho_air_zw(k)
[1691]1732
[2232]1733             ENDDO     
1734          ENDIF
[1691]1735
[2232]1736!
1737!--       Compute v'w' for the total model domain.
1738!--       First compute the corresponding component of u* and square it.
1739!--       Upward-facing surfaces
1740          IF ( .NOT. downward )  THEN
1741             !$OMP PARALLEL DO PRIVATE( i, j, k, z_mo )
[3634]1742             !$ACC PARALLEL LOOP PRIVATE(i, j, k, z_mo) &
1743             !$ACC PRESENT(surf, v, rho_air_zw)
[2232]1744             DO  m = 1, surf%ns 
1745                i = surf%i(m)           
1746                j = surf%j(m)
1747                k = surf%k(m)
[1691]1748
[2232]1749                z_mo = surf%z_mo(m)
[1691]1750
[2232]1751                surf%vsws(m) = kappa * ( v(k,j,i) - v(k-1,j,i) )               &
1752                           / ( LOG( z_mo / surf%z0(m) )                        &
1753                               - psi_m( z_mo / surf%ol(m) )                    &
1754                               + psi_m( surf%z0(m) / surf%ol(m) ) )
[1691]1755!
[2232]1756!--             Please note, the computation of vsws is not fully accurate. Actually
1757!--             a further interpolation of us onto the v-grid, where vsws is defined,
1758!--             is required. However, this is not done as this would require several
1759!--             data transfers between 2D-grid and the surf-type.
1760!--             The impact of the missing interpolation is negligible as several
1761!--             tests had shown.
1762!--             Same also for ol. 
1763                surf%vsws(m) = -surf%vsws(m) * surf%us(m) * rho_air_zw(k-1)
1764             ENDDO
1765!
1766!--       Downward-facing surfaces
1767          ELSE
1768             !$OMP PARALLEL DO PRIVATE( i, j, k, z_mo )
1769             DO  m = 1, surf%ns 
1770                i = surf%i(m)           
1771                j = surf%j(m)
1772                k = surf%k(m)
[1691]1773
[2232]1774                z_mo = surf%z_mo(m)
1775
1776                surf%vsws(m) = kappa * v(k,j,i) / LOG( z_mo / surf%z0(m) )
1777                surf%vsws(m) = surf%vsws(m) * surf%us(m) * rho_air_zw(k)
1778             ENDDO
1779          ENDIF
[1691]1780!
[2232]1781!--       Compute the vertical kinematic heat flux
[2299]1782          IF (  .NOT.  constant_heatflux  .AND.  ( ( time_since_reference_point&
1783               <=  skip_time_do_lsm  .AND. simulated_time > 0.0_wp ) .OR.      &
[2696]1784               .NOT.  land_surface )  .AND.  .NOT. urban_surface  .AND.        &
[2299]1785               .NOT. downward )  THEN
[2232]1786             !$OMP PARALLEL DO PRIVATE( i, j, k )
1787             DO  m = 1, surf%ns 
1788                i    = surf%i(m)           
1789                j    = surf%j(m)
1790                k    = surf%k(m)
1791                surf%shf(m) = -surf%ts(m) * surf%us(m) * rho_air_zw(k-1)
[1691]1792             ENDDO
[2232]1793          ENDIF
1794!
1795!--       Compute the vertical water flux
1796          IF (  .NOT.  constant_waterflux  .AND.  humidity  .AND.              &
[2299]1797               ( ( time_since_reference_point <= skip_time_do_lsm  .AND.       &
[2696]1798               simulated_time > 0.0_wp ) .OR.  .NOT.  land_surface  )  .AND.   &
1799               .NOT.  urban_surface  .AND.  .NOT. downward )  THEN
[2232]1800             !$OMP PARALLEL DO PRIVATE( i, j, k )
1801             DO  m = 1, surf%ns 
1802                i    = surf%i(m)           
1803                j    = surf%j(m)
1804                k    = surf%k(m)
1805                surf%qsws(m) = -surf%qs(m) * surf%us(m) * rho_air_zw(k-1)
1806             ENDDO
1807          ENDIF
1808!
1809!--       Compute the vertical scalar flux
1810          IF (  .NOT.  constant_scalarflux  .AND.  passive_scalar  .AND.       &
1811                .NOT.  downward )  THEN
[2281]1812             !$OMP PARALLEL DO PRIVATE( i, j )
[2232]1813             DO  m = 1, surf%ns   
[1691]1814
[2232]1815                i    = surf%i(m)           
1816                j    = surf%j(m)
1817                surf%ssws(m) = -surf%ss(m) * surf%us(m)
[1691]1818
[2232]1819             ENDDO
[2292]1820          ENDIF   
[1691]1821!
[2696]1822!--       Compute the vertical chemical species' flux
1823          DO  lsp = 1, nvar
1824             IF (  .NOT.  constant_csflux(lsp)  .AND.  air_chemistry  .AND.    &
1825                   .NOT.  downward )  THEN
1826                !$OMP PARALLEL DO PRIVATE( i, j )
1827                DO  m = 1, surf%ns   
1828                   i     = surf%i(m)           
1829                   j     = surf%j(m)
1830                   surf%cssws(lsp,m) = -surf%css(lsp,m) * surf%us(m)
1831                ENDDO
1832             ENDIF   
1833          ENDDO
1834
1835!
[2292]1836!--       Compute (turbulent) fluxes of cloud water content and cloud drop conc.
[3274]1837          IF ( bulk_cloud_model  .AND.  microphysics_morrison  .AND.           &
[2292]1838               .NOT. downward)  THEN
1839             !$OMP PARALLEL DO PRIVATE( i, j )
1840             DO  m = 1, surf%ns   
1841
1842                i    = surf%i(m)           
1843                j    = surf%j(m)
1844
1845                surf%qcsws(m) = -surf%qcs(m) * surf%us(m)
1846                surf%ncsws(m) = -surf%ncs(m) * surf%us(m)
1847             ENDDO
1848          ENDIF   
1849!
[2232]1850!--       Compute (turbulent) fluxes of rain water content and rain drop conc.
[3274]1851          IF ( bulk_cloud_model  .AND.  microphysics_seifert  .AND.            &
[2232]1852               .NOT. downward)  THEN
[2281]1853             !$OMP PARALLEL DO PRIVATE( i, j )
[2232]1854             DO  m = 1, surf%ns   
1855
1856                i    = surf%i(m)           
1857                j    = surf%j(m)
1858
1859                surf%qrsws(m) = -surf%qrs(m) * surf%us(m)
1860                surf%nrsws(m) = -surf%nrs(m) * surf%us(m)
[1691]1861             ENDDO
[2232]1862          ENDIF
[1691]1863
[1960]1864!
[2232]1865!--       Bottom boundary condition for the TKE.
1866          IF ( ibc_e_b == 2 )  THEN
1867             !$OMP PARALLEL DO PRIVATE( i, j, k )
1868             DO  m = 1, surf%ns   
1869
1870                i    = surf%i(m)           
1871                j    = surf%j(m)
1872                k    = surf%k(m)
1873
1874                e(k,j,i) = ( surf%us(m) / 0.1_wp )**2
1875!
1876!--             As a test: cm = 0.4
1877!               e(k,j,i) = ( us(j,i) / 0.4_wp )**2
1878                e(k-1,j,i)   = e(k,j,i)
1879
[1960]1880             ENDDO
[2232]1881          ENDIF
1882!
1883!--    Calcuate surface fluxes at vertical surfaces. No stability is considered.
1884       ELSE
1885!
1886!--       Compute usvs l={0,1} and vsus l={2,3}
1887          IF ( mom_uv )  THEN
1888!
1889!--          Generalize computation by introducing flags. At north- and south-
1890!--          facing surfaces u-component is used, at east- and west-facing
1891!--          surfaces v-component is used.
1892             flag_u = MERGE( 1.0_wp, 0.0_wp, l == 0  .OR.  l == 1 )   
1893             flag_v = MERGE( 1.0_wp, 0.0_wp, l == 2  .OR.  l == 3 )   
1894             !$OMP PARALLEL  DO PRIVATE( i, j, k, z_mo )
1895             DO  m = 1, surf%ns 
1896                i = surf%i(m)           
1897                j = surf%j(m)
1898                k = surf%k(m)
[1691]1899
[2232]1900                z_mo = surf%z_mo(m)
[1960]1901
[2232]1902                surf%mom_flux_uv(m) = kappa *                                  &
1903                                ( flag_u * u(k,j,i) + flag_v * v(k,j,i) )  /   &
1904                                                        LOG( z_mo / surf%z0(m) )
1905
1906               surf%mom_flux_uv(m) =                                           &
1907                                    - surf%mom_flux_uv(m) * surf%us(m)
1908             ENDDO
1909          ENDIF
[1691]1910!
[2232]1911!--       Compute wsus l={0,1} and wsvs l={2,3}
1912          IF ( mom_w )  THEN
1913             !$OMP PARALLEL  DO PRIVATE( i, j, k, z_mo )
1914             DO  m = 1, surf%ns 
1915                i = surf%i(m)           
1916                j = surf%j(m)
1917                k = surf%k(m)
1918
1919                z_mo = surf%z_mo(m)
1920
1921                surf%mom_flux_w(m) = kappa * w(k,j,i) / LOG( z_mo / surf%z0(m) )
1922
1923                surf%mom_flux_w(m) =                                           &
1924                                     - surf%mom_flux_w(m) * surf%us(m)
[1691]1925             ENDDO
[2232]1926          ENDIF
1927!
1928!--       Compute momentum fluxes used for subgrid-scale TKE production at
1929!--       vertical surfaces. In constrast to the calculated momentum fluxes at
1930!--       vertical surfaces before, which are defined on the u/v/w-grid,
1931!--       respectively), the TKE fluxes are defined at the scalar grid.
1932!--       
1933          IF ( mom_tke )  THEN
1934!
1935!--          Precalculate velocity components at scalar grid point.
1936             ALLOCATE( u_i(1:surf%ns) )
1937             ALLOCATE( v_i(1:surf%ns) )
1938             ALLOCATE( w_i(1:surf%ns) )
[1691]1939
[2232]1940             IF ( l == 0  .OR.  l == 1 )  THEN
1941                !$OMP PARALLEL DO PRIVATE( i, j, k )
1942                DO  m = 1, surf%ns 
1943                   i = surf%i(m)           
1944                   j = surf%j(m)
1945                   k = surf%k(m)
1946
1947                   u_i(m) = 0.5_wp * ( u(k,j,i) + u(k,j,i+1) )
1948                   v_i(m) = 0.0_wp
1949                   w_i(m) = 0.5_wp * ( w(k,j,i) + w(k-1,j,i) )
1950                ENDDO
1951             ELSE
1952                !$OMP PARALLEL DO PRIVATE( i, j, k )
1953                DO  m = 1, surf%ns 
1954                   i = surf%i(m)           
1955                   j = surf%j(m)
1956                   k = surf%k(m)
1957
1958                   u_i(m) = 0.0_wp
1959                   v_i(m) = 0.5_wp * ( v(k,j,i) + v(k,j+1,i) )
1960                   w_i(m) = 0.5_wp * ( w(k,j,i) + w(k-1,j,i) )
1961                ENDDO
1962             ENDIF
1963
[2281]1964             !$OMP PARALLEL DO PRIVATE( i, j, dum, z_mo )
[2232]1965             DO  m = 1, surf%ns 
1966                i = surf%i(m)           
1967                j = surf%j(m)
1968
1969                z_mo = surf%z_mo(m)
1970
1971                dum = kappa / LOG( z_mo / surf%z0(m) )
[1691]1972!
[2232]1973!--             usvs (l=0,1) and vsus (l=2,3)
1974                surf%mom_flux_tke(0,m) = dum * ( u_i(m) + v_i(m) )
[1691]1975!
[2232]1976!--             wsvs (l=0,1) and wsus (l=2,3)
1977                surf%mom_flux_tke(1,m) = dum * w_i(m)
1978
1979                surf%mom_flux_tke(0:1,m) =                                     &
1980                               - surf%mom_flux_tke(0:1,m) * surf%us(m)
[1691]1981             ENDDO
[2232]1982!
1983!--          Deallocate temporary arrays
1984             DEALLOCATE( u_i )             
1985             DEALLOCATE( v_i ) 
1986             DEALLOCATE( w_i ) 
1987          ENDIF
[1691]1988       ENDIF
1989
1990    END SUBROUTINE calc_surface_fluxes
1991
[3597]1992   
1993!------------------------------------------------------------------------------!
1994! Description:
1995! ------------
1996!> Calculates temperature near surface (10 cm) for indoor model or 2 m
1997!> temperature for output
1998!------------------------------------------------------------------------------!
1999    SUBROUTINE calc_pt_near_surface ( z_char )
[1691]2000
[3597]2001       IMPLICIT NONE
2002
[3787]2003       CHARACTER (LEN = *), INTENT(IN)       :: z_char       !< string identifier to identify z level
2004       INTEGER(iwp)                          :: i, j, k, m   !< running indices
[3597]2005
2006       
2007       SELECT CASE ( z_char)
2008           
2009       
2010          CASE ( '10cm' )
2011
2012             DO  m = 1, surf%ns
2013
2014                i = surf%i(m)
2015                j = surf%j(m)
2016                k = surf%k(m)
2017
[3744]2018                surf%pt_10cm(m) = surf%pt_surface(m) + surf%ts(m) / kappa      &
2019                                   * ( LOG( 0.1_wp /  surf%z0h(m) )            &
2020                                  - psi_h( 0.1_wp / surf%ol(m) )               &
[3597]2021                                     + psi_h( surf%z0h(m) / surf%ol(m) ) )
[3744]2022                                   
[3597]2023             ENDDO
2024
2025
2026          CASE ( '2m' )
2027     
2028             DO  m = 1, surf%ns
2029
2030                i = surf%i(m)
2031                j = surf%j(m)
2032                k = surf%k(m)
2033
[3744]2034                surf%pt_2m(m) = surf%pt_surface(m) + surf%ts(m) / kappa        &
2035                                   * ( LOG( 2.0_wp /  surf%z0h(m) )            &
2036                                     - psi_h( 2.0_wp / surf%ol(m) )            &
[3597]2037                                     + psi_h( surf%z0h(m) / surf%ol(m) ) )
2038
2039             ENDDO
2040         
2041       
2042       END SELECT
2043
2044    END SUBROUTINE calc_pt_near_surface
2045   
2046
[1691]2047!
2048!-- Integrated stability function for momentum
2049    FUNCTION psi_m( zeta ) 
[3634]2050       !$ACC ROUTINE SEQ
[1691]2051       
2052       USE kinds
2053
2054       IMPLICIT NONE
2055
2056       REAL(wp)            :: psi_m !< Integrated similarity function result
2057       REAL(wp)            :: zeta  !< Stability parameter z/L
2058       REAL(wp)            :: x     !< dummy variable
2059
2060       REAL(wp), PARAMETER :: a = 1.0_wp            !< constant
2061       REAL(wp), PARAMETER :: b = 0.66666666666_wp  !< constant
2062       REAL(wp), PARAMETER :: c = 5.0_wp            !< constant
2063       REAL(wp), PARAMETER :: d = 0.35_wp           !< constant
2064       REAL(wp), PARAMETER :: c_d_d = c / d         !< constant
2065       REAL(wp), PARAMETER :: bc_d_d = b * c / d    !< constant
2066
2067
2068       IF ( zeta < 0.0_wp )  THEN
[1788]2069          x = SQRT( SQRT( 1.0_wp  - 16.0_wp * zeta ) )
[1691]2070          psi_m = pi * 0.5_wp - 2.0_wp * ATAN( x ) + LOG( ( 1.0_wp + x )**2    &
2071                  * ( 1.0_wp + x**2 ) * 0.125_wp )
2072       ELSE
2073
2074          psi_m = - b * ( zeta - c_d_d ) * EXP( -d * zeta ) - a * zeta         &
2075                   - bc_d_d
2076!
2077!--       Old version for stable conditions (only valid for z/L < 0.5)
2078!--       psi_m = - 5.0_wp * zeta
2079
2080       ENDIF
2081
2082    END FUNCTION psi_m
2083
2084
2085!
2086!-- Integrated stability function for heat and moisture
2087    FUNCTION psi_h( zeta ) 
[3634]2088       !$ACC ROUTINE SEQ
[1691]2089       
2090       USE kinds
2091
2092       IMPLICIT NONE
2093
2094       REAL(wp)            :: psi_h !< Integrated similarity function result
2095       REAL(wp)            :: zeta  !< Stability parameter z/L
2096       REAL(wp)            :: x     !< dummy variable
2097
2098       REAL(wp), PARAMETER :: a = 1.0_wp            !< constant
2099       REAL(wp), PARAMETER :: b = 0.66666666666_wp  !< constant
2100       REAL(wp), PARAMETER :: c = 5.0_wp            !< constant
2101       REAL(wp), PARAMETER :: d = 0.35_wp           !< constant
2102       REAL(wp), PARAMETER :: c_d_d = c / d         !< constant
2103       REAL(wp), PARAMETER :: bc_d_d = b * c / d    !< constant
2104
2105
2106       IF ( zeta < 0.0_wp )  THEN
[1788]2107          x = SQRT( 1.0_wp  - 16.0_wp * zeta )
[1691]2108          psi_h = 2.0_wp * LOG( (1.0_wp + x ) / 2.0_wp )
2109       ELSE
2110          psi_h = - b * ( zeta - c_d_d ) * EXP( -d * zeta ) - (1.0_wp          &
2111                  + 0.66666666666_wp * a * zeta )**1.5_wp - bc_d_d             &
2112                  + 1.0_wp
2113!
2114!--       Old version for stable conditions (only valid for z/L < 0.5)
2115!--       psi_h = - 5.0_wp * zeta
2116       ENDIF
2117
2118    END FUNCTION psi_h
2119
[3130]2120
2121!------------------------------------------------------------------------------!
2122! Description:
2123! ------------
2124!> Calculates stability function for momentum
2125!>
2126!> @author Hauke Wurps
2127!------------------------------------------------------------------------------!
2128    FUNCTION phi_m( zeta ) 
[3634]2129       !$ACC ROUTINE SEQ
[3130]2130   
2131       IMPLICIT NONE
2132   
2133       REAL(wp)            :: phi_m         !< Value of the function
2134       REAL(wp)            :: zeta          !< Stability parameter z/L
2135   
2136       REAL(wp), PARAMETER :: a = 16.0_wp   !< constant
2137       REAL(wp), PARAMETER :: c = 5.0_wp    !< constant
2138   
2139       IF ( zeta < 0.0_wp )  THEN
2140          phi_m = 1.0_wp / SQRT( SQRT( 1.0_wp - a * zeta ) )
2141       ELSE
2142          phi_m = 1.0_wp + c * zeta
2143       ENDIF
2144   
2145    END FUNCTION phi_m
2146
[1697]2147 END MODULE surface_layer_fluxes_mod
Note: See TracBrowser for help on using the repository browser.