source: trunk/LMDZ.COMMON/libf/evolution/xios_data.F90 @ 3989

Last change on this file since 3989 was 3989, checked in by jbclement, 5 weeks ago

PEM:
Massive structural refactor of the PEM codebase for improved readability, consistency and maintainability. The goal is to modernize, standardize and consolidate the code while removing legacy complexity. In detail, this change:

  • Performs large-scale cleanup removing unused code, obsolete routines, duplicated functionality and deprecated initialization logic;
  • Removes "*_mod" wrappers;
  • Replaces mixed naming conventions with clearer variable names, domain-based file/module names and purpose-based routine names;
  • Adds native reading/writing capabilities to the PEM removing the cumbersome dependency on Mars PCM subroutines;
  • Centralizes soil/ice/orbital/PEM configuration logic into dedicated modules;
  • Simplifies routines and updates calls/interfaces to match the new structure.

This refactor significantly clarifies the codebase and provides a cleaner foundation for forthcoming developments.
JBC

File size: 11.8 KB
Line 
1MODULE xios_data
2
3use netcdf, only: nf90_open, nf90_close, nf90_inquire_dimension, nf90_inq_dimid, nf90_noerr, nf90_nowrite, nf90_get_var, nf90_inq_varid
4
5implicit none
6
7character(19), parameter :: file1_daily  = "Xoutdaily4pem_Y1.nc"
8character(19), parameter :: file2_daily  = "Xoutdaily4pem_Y2.nc"
9character(20), parameter :: file1_yearly = "Xoutyearly4pem_Y1.nc"
10character(20), parameter :: file2_yearly = "Xoutyearly4pem_Y2.nc"
11character(256)           :: msg      ! For reading
12integer                  :: fID, vID ! For reading
13
14interface get_var
15    module procedure get_var_1d, get_var_2d, get_var_3d, get_var_4d
16end interface get_var
17
18!=======================================================================
19contains
20!=======================================================================
21
22!=======================================================================
23SUBROUTINE load_xios_data(ngrid,nslope,nsoil_PCM,nsol,h2ofrost_PCM,co2frost_PCM,ps_avg,tsurf_avg,tsurf_avg_y1,tsoil_avg,tsoil_ts,watersurf_density_avg,d_h2oice,d_co2ice, &
24                         ps_ts,q_h2o_ts,q_co2_ts,watersoil_density_ts,min_h2oice,min_co2ice)
25
26use grid_conversion, only: lonlat2vect
27use soil,            only: do_soil
28use tendencies,      only: compute_tend
29use metamorphism,    only: compute_frost
30
31implicit none
32
33! Arguments
34!----------
35integer,                       intent(in) :: ngrid, nslope, nsoil_PCM, nsol
36real, dimension(ngrid,nslope), intent(in) :: h2ofrost_PCM, co2frost_PCM
37real, dimension(ngrid),                       intent(out) :: ps_avg
38real, dimension(ngrid,nslope),                intent(out) :: tsurf_avg, tsurf_avg_y1, watersurf_density_avg, d_h2oice, d_co2ice, min_h2oice, min_co2ice
39real, dimension(ngrid,nsoil_PCM,nslope),      intent(out) :: tsoil_avg
40real, dimension(ngrid,nsol),                  intent(out) :: ps_ts, q_h2o_ts, q_co2_ts
41real, dimension(ngrid,nsoil_PCM,nslope,nsol), intent(out) :: tsoil_ts, watersoil_density_ts
42
43! Local variables
44!----------------
45integer                               :: islope, isoil, isol, nlon, nlat
46real, dimension(:,:),     allocatable :: var_read_2d
47real, dimension(:,:,:),   allocatable :: var_read_3d
48real, dimension(:,:,:,:), allocatable :: var_read_4d
49character(:),             allocatable :: num ! For reading slope variables
50real, dimension(ngrid,nslope,2)       :: min_h2operice, min_co2perice, min_h2ofrost, min_co2frost
51
52! Code
53!-----
54! Initialization
55min_h2operice = 0.
56min_co2perice = 0.
57min_h2ofrost = 0.
58min_co2frost = 0.
59if (nslope == 1) then ! No slope
60    allocate(character(0) :: num)
61else ! Using slopes
62    allocate(character(8) :: num)
63endif
64
65!~~~~~~~~~~~~~~~~~~~~~~~~ Year 1 - Yearly data ~~~~~~~~~~~~~~~~~~~~~~~~~
66! Open the NetCDF file of XIOS outputs
67write(*,*) "Opening "//file1_yearly//"..."
68call error_msg(nf90_open(file1_yearly,nf90_nowrite,fID),'open',file1_yearly)
69
70! Get the dimensions
71call error_msg(nf90_inq_dimid(fID,'lon',vID),'inq',file1_yearly)
72call error_msg(nf90_inquire_dimension(fID,vID,len = nlon),'inq',file1_yearly)
73call error_msg(nf90_inq_dimid(fID,'lat',vID),'inq',file1_yearly)
74call error_msg(nf90_inquire_dimension(fID,vID,len = nlat),'inq',file1_yearly)
75
76! Allocate and read the variables
77allocate(var_read_2d(nlon,nlat),var_read_3d(nlon,nlat,nsoil_PCM))
78do islope = 1,nslope
79    if (nslope /= 1) then
80        num='  '
81        write(num,'(i2.2)') islope
82        num = '_slope'//num
83    endif
84    call get_var('co2ice'//num,var_read_2d)          ; call lonlat2vect(nlon,nlat,ngrid,var_read_2d,min_co2frost(:,islope,1))
85    call get_var('h2o_ice_s'//num,var_read_2d)       ; call lonlat2vect(nlon,nlat,ngrid,var_read_2d,min_h2ofrost(:,islope,1))
86    call get_var('watercap'//num,var_read_2d)        ; call lonlat2vect(nlon,nlat,ngrid,var_read_2d,min_h2operice(:,islope,1))
87    call get_var('perennial_co2ice'//num,var_read_2d); call lonlat2vect(nlon,nlat,ngrid,var_read_2d,min_co2perice(:,islope,1))
88    call get_var('tsurf'//num,var_read_2d)           ; call lonlat2vect(nlon,nlat,ngrid,var_read_2d,tsurf_avg_y1(:,islope))
89enddo
90
91! Close the NetCDF file of XIOS outputs
92call error_msg(nf90_close(fID),"close",file1_yearly)
93write(*,*) '> Data from "'//file1_yearly//'" downloaded!'
94
95!~~~~~~~~~~~~~~~~~~~~~~~~ Year 2 - Yearly data ~~~~~~~~~~~~~~~~~~~~~~~~~
96! Open the NetCDF file of XIOS outputs
97write(*,*) "Opening "//file2_yearly//"..."
98call error_msg(nf90_open(file2_yearly,nf90_nowrite,fID),'open',file2_yearly)
99
100! Allocate and read the variables
101call get_var('ps',var_read_2d); call lonlat2vect(nlon,nlat,ngrid,var_read_2d,ps_avg)
102do islope = 1,nslope
103    if (nslope /= 1) then
104        num='  '
105        write(num,'(i2.2)') islope
106        num = '_slope'//num
107    endif
108    call get_var('tsurf'//num,var_read_2d)           ; call lonlat2vect(nlon,nlat,ngrid,var_read_2d,tsurf_avg(:,islope))
109    call get_var('co2ice'//num,var_read_2d)          ; call lonlat2vect(nlon,nlat,ngrid,var_read_2d,min_co2frost(:,islope,2))
110    call get_var('h2o_ice_s'//num,var_read_2d)       ; call lonlat2vect(nlon,nlat,ngrid,var_read_2d,min_h2ofrost(:,islope,2))
111    call get_var('watercap'//num,var_read_2d)        ; call lonlat2vect(nlon,nlat,ngrid,var_read_2d,min_h2operice(:,islope,2))
112    call get_var('perennial_co2ice'//num,var_read_2d); call lonlat2vect(nlon,nlat,ngrid,var_read_2d,min_co2perice(:,islope,2))
113    if (do_soil) then
114        call get_var('soiltemp'//num,var_read_3d)
115        do isoil = 1,nsoil_PCM
116            call lonlat2vect(nlon,nlat,ngrid,var_read_3d(:,:,isoil),tsoil_avg(:,isoil,islope))
117        enddo
118        call get_var('waterdensity_surface'//num,var_read_2d); call lonlat2vect(nlon,nlat,ngrid,var_read_2d,watersurf_density_avg(:,islope))
119    endif
120enddo
121! Close the NetCDF file of XIOS outputs
122call error_msg(nf90_close(fID),"close",file1_yearly)
123write(*,*) '> Data from "'//file1_yearly//'" downloaded!'
124
125!~~~~~~~~~~~~~~~~~~~~~~~~~ Year 2 - Daily data ~~~~~~~~~~~~~~~~~~~~~~~~~
126! Open the NetCDF file of XIOS outputs
127write(*,*) "Opening "//file2_daily//"..."
128call error_msg(nf90_open(file2_daily,nf90_nowrite,fID),'open',file2_daily)
129
130! Allocate and read the variables
131deallocate(var_read_2d,var_read_3d)
132allocate(var_read_3d(nlon,nlat,nsol),var_read_4d(nlon,nlat,nsoil_PCM,nsol))
133call get_var('ps',var_read_3d)
134do isol = 1,nsoil_PCM
135    call lonlat2vect(nlon,nlat,ngrid,var_read_3d(:,:,isol),ps_ts(:,isol))
136enddo
137call get_var('h2o_layer1',var_read_3d)
138do isol = 1,nsoil_PCM
139    call lonlat2vect(nlon,nlat,ngrid,var_read_3d(:,:,isol),q_h2o_ts(:,isol))
140enddo
141call get_var('co2_layer1',var_read_3d)
142do isol = 1,nsoil_PCM
143    call lonlat2vect(nlon,nlat,ngrid,var_read_3d(:,:,isol),q_co2_ts(:,isol))
144enddo
145if (do_soil) then
146    do islope = 1,nslope
147        if (nslope /= 1) then
148            num='  '
149            write(num,'(i2.2)') islope
150            num = '_slope'//num
151        endif
152        call get_var('soiltemp'//num,var_read_4d)
153        do isol = 1,nsol
154            do isoil = 1,nsoil_PCM
155                call lonlat2vect(nlon,nlat,ngrid,var_read_4d(:,:,isoil,isol),tsoil_ts(:,isoil,islope,isol))
156            enddo
157        enddo
158        call get_var('waterdensity_soil'//num,var_read_4d)
159        do isol = 1,nsol
160            do isoil = 1,nsoil_PCM
161                call lonlat2vect(nlon,nlat,ngrid,var_read_4d(:,:,isoil,isol),watersoil_density_ts(:,isoil,islope,isol))
162            enddo
163        enddo
164    enddo
165endif
166deallocate(var_read_3d,var_read_4d,num)
167
168! Close the NetCDF file of XIOS outputs
169call error_msg(nf90_close(fID),"close",file1_daily)
170write(*,*) '> Data from "'//file2_daily//'" downloaded!'
171
172!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
173! Compute frost from yearly minima
174call compute_frost(ngrid,nslope,h2ofrost_PCM,min_h2ofrost,co2frost_PCM,min_co2frost)
175
176!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
177! Compute ice tendencies from yearly minima
178write(*,*) '> Computing surface ice tendencies'
179call compute_tend(ngrid,nslope,min_h2operice + min_h2ofrost,d_h2oice)
180write(*,*) 'H2O ice tendencies (min/max):', minval(d_h2oice), maxval(d_h2oice)
181call compute_tend(ngrid,nslope,min_co2perice + min_co2frost,d_co2ice)
182write(*,*) 'CO2 ice tendencies (min/max):', minval(d_co2ice), maxval(d_co2ice)
183
184END SUBROUTINE load_xios_data
185!=======================================================================
186
187!=======================================================================
188SUBROUTINE get_timelen(filename,timelen)
189
190use netcdf
191
192implicit none
193
194! Arguments
195! ---------
196character(*), intent(in)  :: filename
197integer,      intent(out) :: timelen
198
199! Local variables
200! ---------------
201integer :: ncid  ! File ID
202integer :: dimid ! Dimension ID
203integer :: ierr  ! Return codes
204
205! Code
206! ----
207! Open the NetCDF file
208ierr = nf90_open(trim(filename),NF90_NOWRITE,ncid)
209if (ierr /= nf90_noerr) then
210    write(*,*) "Error opening file:", trim(nf90_strerror(ierr))
211    error stop
212endif
213
214! Get the dimension ID for 'time_counter'
215ierr = nf90_inq_dimid(ncid,"time_counter",dimid)
216if (ierr /= nf90_noerr) then
217    write(*,*) "Error getting dimid 'time_counter':", trim(nf90_strerror(ierr))
218    error stop
219endif
220
221! Get the size of the dimension 'time_counter'
222ierr = nf90_inquire_dimension(ncid,dimid,len = timelen)
223if (ierr /= nf90_noerr) then
224    write(*,*) "Error getting dimension length:", trim(nf90_strerror(ierr))
225    error stop
226endif
227
228! Close the file
229ierr = nf90_close(ncid)
230if (ierr /= nf90_noerr) then
231    write(*,*) "Error closing file:", trim(nf90_strerror(ierr))
232    error stop
233endif
234
235END SUBROUTINE get_timelen
236!=======================================================================
237
238!=======================================================================
239SUBROUTINE error_msg(ierr,typ,nam)
240
241implicit none
242
243integer,      intent(in) :: ierr !--- NetCDF error code
244character(*), intent(in) :: typ  !--- Type of operation
245character(*), intent(in) :: nam  !--- Field/File name
246
247if (ierr == nf90_noerr) return
248select case(typ)
249    case('inq')  ; msg = "Dim/Field <"//trim(nam)//"> is missing"
250    case('get')  ; msg = "Reading failed for <"//trim(nam)//">"
251    case('put')  ; msg = "Writing failed for <"//trim(nam)//">"
252    case('open') ; msg = "File opening failed for <"//trim(nam)//">"
253    case('close'); msg = "File closing failed for <"//trim(nam)//">"
254    case default
255        write(*,*) 'There is no message for this error.'
256        error stop
257end select
258call abort_gcm(__FILE__,trim(msg),ierr)
259
260END SUBROUTINE error_msg
261!=======================================================================
262
263!=======================================================================
264SUBROUTINE get_var_1d(var,v)
265
266implicit none
267
268character(*), intent(in) :: var
269real, dimension(:), intent(out) :: v
270
271call error_msg(nf90_inq_varid(fID,var,vID),"inq",var)
272call error_msg(nf90_get_var(fID,vID,v),"get",var)
273
274END SUBROUTINE get_var_1d
275!=======================================================================
276
277!=======================================================================
278SUBROUTINE get_var_2d(var,v)
279
280implicit none
281
282character(*), intent(in) :: var
283real, dimension(:,:), intent(out) :: v
284
285call error_msg(nf90_inq_varid(fID,var,vID),"inq",var)
286call error_msg(nf90_get_var(fID,vID,v),"get",var)
287
288END SUBROUTINE get_var_2d
289!=======================================================================
290
291!=======================================================================
292SUBROUTINE get_var_3d(var,v)
293
294implicit none
295
296character(*), intent(in) :: var
297real, dimension(:,:,:), intent(out) :: v
298
299call error_msg(nf90_inq_varid(fID,var,vID),"inq",var)
300call error_msg(nf90_get_var(fID,vID,v),"get",var)
301
302END SUBROUTINE get_var_3d
303!=======================================================================
304
305!=======================================================================
306SUBROUTINE get_var_4d(var,v)
307
308implicit none
309
310character(*), intent(in) :: var
311real, dimension(:,:,:,:), intent(out) :: v
312
313call error_msg(nf90_inq_varid(fID,var,vID),"inq",var)
314call error_msg(nf90_get_var(fID,vID,v),"get",var)
315
316END SUBROUTINE get_var_4d
317!=======================================================================
318
319END MODULE xios_data
Note: See TracBrowser for help on using the repository browser.