source: codes/icosagcm/devel/src/diagnostics/diagflux.F90 @ 595

Last change on this file since 595 was 595, checked in by dubos, 7 years ago

devel : fix halo issues with computation of energy fluxes

File size: 6.9 KB
Line 
1MODULE diagflux_mod
2  USE icosa
3  USE omp_para
4  IMPLICIT NONE
5  SAVE
6  PRIVATE
7
8  TYPE(t_field), POINTER, PUBLIC :: &
9       f_masst(:), f_qmasst(:), & ! time-averaged mass, tracer mass,
10       f_massfluxt(:), f_qfluxt(:), & ! time-integrated mass flux and tracer flux
11       f_qfluxt_lon(:), f_qfluxt_lat(:), & ! scalar flux reconstructed at cell centers
12       f_epot(:), f_ekin(:), f_enthalpy(:), & ! time-averaged potential E, kinetic E and enthalpy
13       f_epotfluxt(:), f_ekinfluxt(:), f_enthalpyfluxt(:) ! time averaged 'fluxes' of epot, ekin and enthalpy
14  LOGICAL :: diagflux_on
15  !$OMP THREADPRIVATE(diagflux_on)
16
17  PUBLIC :: diagflux_on, init_diagflux, zero_qfluxt, qflux_centered_lonlat, flux_centered_lonlat, diagflux_energy
18
19CONTAINS
20
21  SUBROUTINE init_diagflux
22    USE getin_mod
23    INTEGER :: ll
24    diagflux_on = .FALSE.
25    CALL getin("diagflux", diagflux_on)
26    ll = MERGE(llm,1,diagflux_on)
27    CALL allocate_field(f_masst,         field_t,type_real,ll,       name="masst")
28    CALL allocate_field(f_epot,          field_t,type_real,ll,       name="epot")
29    CALL allocate_field(f_ekin,          field_t,type_real,ll,       name="ekin")
30    CALL allocate_field(f_enthalpy,      field_t,type_real,ll,       name="enthalpy")
31    CALL allocate_field(f_qmasst,        field_t,type_real,ll,nqtot, name="qmasst")
32    CALL allocate_field(f_massfluxt,     field_u,type_real,ll,       name="massfluxt")
33    CALL allocate_field(f_epotfluxt,     field_u,type_real,ll,       name="epotfluxt")
34    CALL allocate_field(f_ekinfluxt,     field_u,type_real,ll,       name="ekinfluxt")
35    CALL allocate_field(f_enthalpyfluxt, field_u,type_real,ll,       name="enthalpyfluxt")
36    CALL allocate_field(f_qfluxt,        field_u,type_real,ll,nqtot, name="qfluxt")
37    CALL allocate_field(f_qfluxt_lon,    field_t,type_real,ll,nqtot, name="qfluxt_lon")
38    CALL allocate_field(f_qfluxt_lat,    field_t,type_real,ll,nqtot, name="qfluxt_lat")
39    IF(diagflux_on) CALL zero_qfluxt
40  END SUBROUTINE init_diagflux
41
42#define ZERO2(field) buf2=field(ind) ; buf2(:,ll_begin:ll_end)=0.
43#define ZERO3(field) buf3=field(ind) ; buf3(:,ll_begin:ll_end,:)=0.
44
45  SUBROUTINE zero_qfluxt
46    INTEGER :: ind
47    REAL(rstd), POINTER :: buf2(:,:),buf3(:,:,:)
48    DO ind=1,ndomain
49       IF (.NOT. assigned_domain(ind)) CYCLE
50       CALL swap_dimensions(ind)
51       ZERO2(f_masst)
52       ZERO2(f_epot)
53       ZERO2(f_ekin)
54       ZERO2(f_enthalpy)
55       ZERO3(f_qmasst)
56       ZERO2(f_massfluxt)
57       ZERO2(f_epotfluxt)
58       ZERO2(f_ekinfluxt)
59       ZERO2(f_enthalpyfluxt)
60       ZERO3(f_qfluxt)
61    END DO
62  END SUBROUTINE zero_qfluxt
63
64!------------------------------------ Reconstruct fluxes at cell centers ---------------------------------------
65
66  SUBROUTINE qflux_centered_lonlat(scale, f_flux, f_flux_lon, f_flux_lat)
67    REAL(rstd), INTENT(IN) :: scale
68    TYPE(t_field),POINTER :: f_flux(:), f_flux_lon(:), f_flux_lat(:)
69    REAL(rstd), POINTER :: flux(:,:,:), flux_lon(:,:,:), flux_lat(:,:,:)
70    INTEGER :: ind, itrac
71    DO ind=1,ndomain
72       IF (.NOT. assigned_domain(ind)) CYCLE
73       CALL swap_dimensions(ind)
74       CALL swap_geometry(ind)
75       flux=f_flux(ind)
76       flux_lon=f_flux_lon(ind)
77       flux_lat=f_flux_lat(ind)
78       DO itrac=1,nqtot
79          CALL compute_flux_centered_lonlat(scale, flux(:,:,itrac), flux_lon(:,:,itrac), flux_lat(:,:,itrac))
80       END DO
81    END DO
82  END SUBROUTINE qflux_centered_lonlat
83 
84  SUBROUTINE flux_centered_lonlat(scale, f_flux, f_flux_lon, f_flux_lat)
85    REAL(rstd), INTENT(IN) :: scale
86    TYPE(t_field),POINTER :: f_flux(:), f_flux_lon(:), f_flux_lat(:)
87    REAL(rstd), POINTER :: flux(:,:), flux_lon(:,:), flux_lat(:,:)
88    INTEGER :: ind
89    DO ind=1,ndomain
90       IF (.NOT. assigned_domain(ind)) CYCLE
91       CALL swap_dimensions(ind)
92       CALL swap_geometry(ind)
93       flux=f_flux(ind)
94       flux_lon=f_flux_lon(ind)
95       flux_lat=f_flux_lat(ind)
96       CALL compute_flux_centered_lonlat(scale, flux, flux_lon, flux_lat)
97    END DO
98  END SUBROUTINE flux_centered_lonlat
99 
100  SUBROUTINE compute_flux_centered_lonlat(scale, flux, flux_lon, flux_lat)
101    USE wind_mod
102    REAL(rstd), INTENT(IN) :: scale
103    REAL(rstd), INTENT(IN) :: flux(3*iim*jjm,llm)
104    REAL(rstd), INTENT(OUT) :: flux_lon(iim*jjm,llm), flux_lat(iim*jjm,llm)
105    REAL(rstd) :: flux_3d(iim*jjm,llm,3)
106    CALL compute_flux_centered(scale, flux, flux_3d)
107    CALL compute_wind_centered_lonlat_compound(flux_3d, flux_lon, flux_lat)
108  END SUBROUTINE compute_flux_centered_lonlat
109
110!------------------------------------ Compute energy fluxes ---------------------------------------
111
112  SUBROUTINE diagflux_energy(frac, f_phis,f_rhodz,f_theta_rhodz,f_u, f_geopot,f_theta, f_hfluxt)
113    REAL(rstd), INTENT(IN) :: frac
114    TYPE(t_field),POINTER :: f_phis(:),f_rhodz(:),f_theta_rhodz(:),f_u(:), f_geopot(:), f_theta(:), f_hfluxt(:)
115    REAL(rstd), POINTER :: phis(:), rhodz(:,:), theta_rhodz(:,:,:), u(:,:), &
116         geopot(:,:), pk(:,:,:), hfluxt(:,:), &
117         epot(:,:), ekin(:,:), enthalpy(:,:), &
118         epotflux(:,:), ekinflux(:,:), enthalpyflux(:,:)
119    INTEGER :: ind
120    DO ind=1,ndomain
121       IF (.NOT. assigned_domain(ind)) CYCLE
122       CALL swap_dimensions(ind)
123       CALL swap_geometry(ind)
124       hfluxt = f_hfluxt(ind)
125       phis = f_phis(ind)
126       rhodz = f_rhodz(ind)
127       theta_rhodz = f_theta_rhodz(ind)
128       u = f_u(ind)
129       geopot = f_geopot(ind)
130       pk = f_theta(ind) ! buffer
131       epot = f_epot(ind)
132       ekin = f_ekin(ind)
133       enthalpy = f_enthalpy(ind)
134       epotflux = f_epotfluxt(ind)
135       ekinflux = f_ekinfluxt(ind)
136       enthalpyflux = f_enthalpyfluxt(ind)
137       CALL compute_diagflux_energy(frac,hfluxt, phis,rhodz,theta_rhodz,u, geopot,pk, epot,ekin,enthalpy, epotflux, ekinflux, enthalpyflux)
138    END DO
139  END SUBROUTINE diagflux_energy
140
141  SUBROUTINE compute_diagflux_energy(frac, massflux, phis,rhodz,theta_rhodz,u, geopot,pk, epot,ekin,enthalpy, epot_flux, ekin_flux, enthalpy_flux)
142    USE disvert_mod, ONLY : ptop
143    REAL(rstd), INTENT(IN) :: frac
144    REAL(rstd), INTENT(IN) :: massflux(3*iim*jjm,llm), u(3*iim*jjm,llm),&
145                              phis(iim*jjm), rhodz(iim*jjm,llm), theta_rhodz(iim*jjm,llm,nqtot)
146    REAL(rstd), INTENT(INOUT) :: geopot(iim*jjm,llm+1), pk(iim*jjm,llm) ! pk = buffer
147    REAL(rstd), INTENT(INOUT), DIMENSION(iim*jjm, llm)   ::  epot, ekin, enthalpy
148    REAL(rstd), INTENT(INOUT), DIMENSION(3*iim*jjm, llm) ::  epot_flux, ekin_flux, enthalpy_flux   
149    REAL(rstd) :: energy, p_ik, theta_ik, temp_ik, gv, Rd 
150    INTEGER :: ij, l, ij_omp_begin_ext, ij_omp_end_ext
151    Rd = kappa*cpp
152    ! even if loops are of the _ext variant, we still need halo exchanges before reconstructing fluxes at cell centers
153    ! => loop over interior region
154    CALL distrib_level(ij_end-ij_begin+1,ij_omp_begin_ext,ij_omp_end_ext)
155    ij_omp_begin_ext = ij_omp_begin_ext+ij_begin-1
156    ij_omp_end_ext = ij_omp_end_ext+ij_begin-1
157#include "../kernels/energy_fluxes.k90"
158  END SUBROUTINE compute_diagflux_energy
159
160END MODULE diagflux_mod
Note: See TracBrowser for help on using the repository browser.