FV3 Bundle
write_ocean_data.F90
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
20 
21  use mpp_io_mod, only : fieldtype, axistype, mpp_open,&
22  mpp_overwr, mpp_netcdf, mpp_multi, mpp_single,&
23  mpp_write_meta, mpp_write, mpp_close
24  use mpp_mod, only : mpp_error, fatal
25  use oda_types_mod, only : missing_value
27  use time_manager_mod, only : time_type, get_time, set_date, operator ( - )
28 
29  implicit none
30 
31  private
32 
39 
40  integer, parameter :: ref_yr=1900, ref_mon=1, ref_day=1,&
41  ref_hr=0, ref_min=0, ref_sec=0,max_files=1000
42 
44 
45  integer,save :: nvar_out
46 
47  integer, save :: sta_num(max_files), unit_num(max_files), nfiles
48 
50 
51  logical :: module_is_initialized=.false.
52 
55 
56 #include <netcdf.inc>
57 
58 contains
59 
60 function open_profile_file(name, nvar, grid_lon, grid_lat,thread,fset)
61 
62  character(len=*), intent(in) :: name
63  integer, intent(in), optional :: nvar
64  real, dimension(:), optional, intent(in) :: grid_lon, grid_lat
65  integer, intent(in), optional :: thread, fset
66 
67  integer :: i, open_profile_file, unit
68  integer :: threading, fileset
69  character(len=128) :: units, time_units
70  real, dimension(max_levels_file) :: array
71 
72 type(axistype) :: depth_axis, station_axis, lon_axis, lat_axis
73 
74 threading=mpp_multi
75 fileset=mpp_single
76 
77 if (PRESENT(thread)) threading=thread
78 if (PRESENT(fset)) fileset=fset
79 
82 call mpp_open(unit, trim(name), action=mpp_overwr, form=mpp_netcdf,&
83  threading=threading, fileset=fileset)
84 
85 open_profile_file = unit
86 
87 nfiles=nfiles+1
88 
89 if (nfiles > max_files) call mpp_error(fatal,'max number of profiles exceeded&
90  &in module write_ocean_data, increase param : max_files')
91 
92 unit_num(nfiles) = unit
93 
94 
95 nvar_out = 2
96 if (PRESENT(nvar)) nvar_out = nvar
97 
98 if (PRESENT(grid_lon) .and. PRESENT(grid_lat)) then
99  call mpp_write_meta(unit, lon_axis, 'grid_longitude','degrees_E',&
100  'observational grid longitude',cartesian='X',sense=1,data=grid_lon)
101 
102  call mpp_write_meta(unit, lat_axis, 'grid_latitude','degrees_N',&
103  'observational grid latitude', cartesian='Y',sense=1,data=grid_lat)
104 endif
105 
106 !call mpp_write_meta(unit,depth_axis,'depth_index','none','depth index',&
107 ! cartesian='Z',sense=-1)!,data=(/(float(i),i=1,max_levels_file)/))
108 !pgf90 complains about the above. This is a compiler bug. Workaround:
109 array = (/(float(i),i=1,max_levels_file)/)
110 call mpp_write_meta(unit,depth_axis,'depth_index','none','depth index',&
111  cartesian='Z',sense=-1,data=array)
112 
113 call mpp_write_meta(unit,station_axis,'station_index','none',&
114  'station index', cartesian='T',sense=1)
115 
116 if (PRESENT(grid_lon) .and. PRESENT(grid_lat)) then
117  call mpp_write_meta(unit, lon_index_field, (/station_axis/),&
118  'longitude_index','none','longitude_index', missing=missing_value)
119  call mpp_write_meta(unit, lat_index_field, (/station_axis/),&
120  'latitude_index','none','latitude_index',missing=missing_value)
121 endif
122 
123 call mpp_write_meta(unit,nvar_field,(/station_axis/),&
124  'nvar','none','temp (1) or temp and salt (2)')
125 
126 call mpp_write_meta(unit,lon_field,(/station_axis/),&
127  'longitude','degrees_E','longitude',&
128  min=-1.0,max=361.0)
129 
130 call mpp_write_meta(unit,lat_field,(/station_axis/),&
131  'latitude','degrees_N','latitude',&
132  min=-91.0,max=91.0)
133 
134 call mpp_write_meta(unit,profile_flag_field,(/station_axis/),&
135  'profile_flag','none','profile_flag',&
136  min=0.0,max=10.0,missing=missing_value)
137 
138 
139 if (nvar_out .eq. 2) call mpp_write_meta(unit,profile_flag_s_field,(/station_axis/),&
140  'profile_flag_s','none','profile_flag for salt',&
141  min=0.0,max=10.0,missing=missing_value)
142 
143 
144 write(time_units,'(a,i4.4,a,i2.2,a,i2.2,a)') 'days since ',ref_yr,'-',ref_mon,'-',ref_day,' 00:00:00'
145 
146 call mpp_write_meta(unit,time_field,(/station_axis/),&
147  'time',trim(time_units),'time')
148 
149 call mpp_write_meta(unit,yyyy_field,(/station_axis/),&
150  'yyyy','none','yyyy')
151 
152 call mpp_write_meta(unit,mmdd_field,(/station_axis/),&
153  'mmdd','none','mmdd')
154 
155 
156 
157 units='deg_C'
158 call mpp_write_meta(unit,temp_err_field,(/station_axis/),&
159  'temp_error',trim(units),'measurement error of temperature',missing=missing_value)
160 
161 units='g/kg'
162 if (nvar_out .eq. 2) call mpp_write_meta(unit,salt_err_field,(/station_axis/),&
163  'salt_error',trim(units),'measurement error of salinity',missing=missing_value)
164 
165 call mpp_write_meta(unit,project_field,(/station_axis/),&
166  'project','none','see NODC codes')
167 
168 call mpp_write_meta(unit,probe_field,(/station_axis/),&
169  'probe','none','see NODC codes')
170 
171 call mpp_write_meta(unit,ref_inst_field,(/station_axis/),&
172  'ref_inst','none','see NODC codes')
173 
174 call mpp_write_meta(unit,fix_depth_field,(/station_axis/),&
175  'fix_depth','none','see NODC codes')
176 
177 call mpp_write_meta(unit,database_id_field,(/station_axis/),&
178  'database_id','none','see NODC codes')
179 
180 call mpp_write_meta(unit,ocn_vehicle_field,(/station_axis/),&
181  'ocn_vehicle','none','see NODC codes')
182 
183 call mpp_write_meta(unit,link_field,(/station_axis/),&
184  'link','none','partial_profile flag')
185 
186 
187  units='degrees_C'
188  call mpp_write_meta(unit,data_t_field,(/depth_axis,station_axis/),&
189  'temp',trim(units),'in-situ temperature',&
190  min=-10.0,max=50.0,missing=missing_value)
191 
192  units='g/kg'
193  if (nvar_out .eq. 2) call mpp_write_meta(unit,data_s_field,(/depth_axis,station_axis/),&
194  'salt',trim(units),'salinity',&
195  min=0.0,max=50.0,missing=missing_value)
196 
197 call mpp_write_meta(unit,depth_field,(/depth_axis,station_axis/),&
198  'depth','meters','depth of obs',&
199  min=0.0,max=7000.0,missing=missing_value)
200 
201 
202 
203 call mpp_write_meta(unit,flag_t_field,(/depth_axis,station_axis/),&
204  'temp_flag','none','temperature level flag (see NODC codes)',missing=missing_value)
205 
206 if (nvar_out .eq. 2) call mpp_write_meta(unit,flag_s_field,(/depth_axis,station_axis/),&
207  'salt_flag','none','salinity level flag (see NODC codes)',missing=missing_value)
208 
209 
210 
211 call mpp_write(unit, depth_axis)
212 
213 if (PRESENT(grid_lon).and.PRESENT(grid_lat)) then
214  call mpp_write(unit, lon_axis)
215  call mpp_write(unit, lat_axis)
216 endif
217 
218 end function open_profile_file
219 
220 
221 subroutine write_profile(unit,profile)
225 use mpp_mod, only : mpp_pe
226 
227 integer, intent(in) :: unit
228 type(ocean_profile_type), intent(in) :: profile
229 
230 real, dimension(max_levels_file) :: data_t, data_s, depth
231 integer :: levels, secs, days, i, j, nlinks
232 real :: profile_flag, profile_flag_s, days_since, error, nvar, station
233 real :: tmp_s
234 real, dimension(max_levels_file) :: flag_t, flag_s
235 logical :: grid_ptr = .false.
236 integer :: findex
237 integer :: isc,iec,jsc,jec,isd,ied,jsd,jed
238 logical :: debug=.false.
239 
240 ! find file index from file unit list
241 
242 findex=-1
243 do i=1,nfiles
244  if (unit_num(i) .eq. unit) then
245  findex=i
246  exit
247  endif
248 enddo
249 
250 if (findex .eq. -1) call mpp_error(fatal,'Attempt write to unopened file in&
251  &write_ocean_data_mod:write_profile_data')
252 
253 
254 sta_num(findex)=sta_num(findex)+1
255 
256 station=sta_num(findex)
257 
258 levels = min(profile%levels,max_levels_file)
259 data_t=missing_value;data_s=missing_value;depth=missing_value
260 flag_t=missing_value;flag_s=missing_value
261 data_t(1:levels)=profile%data_t(1:levels)
262 flag_t(1:levels)=profile%flag_t(1:levels)
263 
264 if (ASSOCIATED(profile%Model_Grid)) grid_ptr = .true.
265 
266 
267 if (grid_ptr) then
268  call mpp_get_compute_domain(profile%Model_Grid%Dom, isc, iec, jsc, jec)
269  if (floor(profile%i_index) .lt. isc .or. floor(profile%i_index) .gt. iec) return
270  if (floor(profile%j_index) .lt. jsc .or. floor(profile%j_index) .gt. jec) return
271 endif
272 
273 if (profile%nvar == 2) then
274  data_s(1:levels) = profile%data_s(1:levels)
275  flag_s(1:levels)=profile%flag_s(1:levels)
276 endif
277 
278 depth(1:levels)=profile%depth(1:levels)
279 time = profile%time - ref_time
280 call get_time(time, secs, days)
281 days_since = days + secs/86400.
282 
283 
284  nvar = profile%nvar
285  call mpp_write(unit,nvar_field,nvar,station)
286  call mpp_write(unit,data_t_field,data_t,station)
287  if (nvar_out .eq. 2) call mpp_write(unit,data_s_field,data_s,station)
288  call mpp_write(unit,depth_field,depth,station)
289  call mpp_write(unit,project_field,profile%project,station)
290  call mpp_write(unit,probe_field,profile%probe,station)
291  call mpp_write(unit,ref_inst_field,profile%ref_inst,station)
292  call mpp_write(unit,fix_depth_field,profile%fix_depth,station)
293  call mpp_write(unit,ocn_vehicle_field,profile%ocn_vehicle,station)
294  call mpp_write(unit,database_id_field,profile%database_id,station)
295  profile_flag = profile%profile_flag
296  call mpp_write(unit,profile_flag_field,profile_flag,station)
297  profile_flag = profile%profile_flag_s
298  if (nvar_out .eq. 2) call mpp_write(unit,profile_flag_s_field,profile_flag,station)
299  call mpp_write(unit,lon_field,profile%lon,station)
300  call mpp_write(unit,lat_field,profile%lat,station)
301  call mpp_write(unit,time_field,days_since,station)
302  tmp_s = real(profile%yyyy)
303  call mpp_write(unit,yyyy_field,tmp_s,station)
304  tmp_s = real(profile%mmdd)
305  call mpp_write(unit,mmdd_field,tmp_s,station)
306  call mpp_write(unit,temp_err_field,profile%temp_err,station)
307  if (nvar_out .eq. 2) call mpp_write(unit,salt_err_field,profile%salt_err,station)
308  nlinks = 0
309 
310  if (profile%levels .gt. max_levels_file) then
311  nlinks = ceiling(float(profile%levels)/float(max_levels_file)) - 1
312  endif
313 
314  if (nlinks .gt. 0) then
315  call mpp_write(unit,link_field,1.,station)
316  else
317  call mpp_write(unit,link_field,0.,station)
318  endif
319 
320 if (profile%i_index .ne. -1.0 .and. profile%j_index .ne. -1.0) then
321  call mpp_write(unit, lon_index_field,profile%i_index)
322  call mpp_write(unit, lat_index_field,profile%j_index)
323 endif
324 
325 do i = 1, nlinks
326  sta_num(findex)=sta_num(findex)+1
327  station=sta_num(findex)
328  if (i.eq.nlinks) then
329  levels = mod(profile%levels,max_levels_file)
330  if (levels .eq. 0) levels = max_levels_file
331  else
332  levels = max_levels_file
333  endif
334  data_t = missing_value; data_s = missing_value; depth = missing_value
335  flag_t=missing_value;flag_s=missing_value
336 
337  data_t(1:levels)=profile%data_t((max_levels_file*i)+1:(max_levels_file*i)+levels)
338  flag_t(1:levels)=profile%flag_t((max_levels_file*i)+1:(max_levels_file*i)+levels)
339 
340  if (profile%nvar == 2) then
341  data_s(1:levels) = profile%data_s((max_levels_file*i)+1:(max_levels_file*i)+levels)
342  flag_s(1:levels)= profile%flag_s((max_levels_file*i)+1:(max_levels_file*i)+levels)
343 
344  endif
345 
346 
347  depth(1:levels)=profile%depth((max_levels_file*i)+1:(max_levels_file*i)+levels)
348 
349  call mpp_write(unit,nvar_field,nvar,station)
350  call mpp_write(unit,data_t_field,data_t,station)
351  if (nvar_out .eq. 2) call mpp_write(unit,data_s_field,data_s,station)
352  call mpp_write(unit,depth_field,depth,station)
353 
354  call mpp_write(unit,project_field,profile%project,station)
355  call mpp_write(unit,probe_field,profile%probe,station)
356  call mpp_write(unit,ref_inst_field,profile%ref_inst,station)
357  call mpp_write(unit,fix_depth_field,profile%fix_depth,station)
358  call mpp_write(unit,ocn_vehicle_field,profile%ocn_vehicle,station)
359  call mpp_write(unit,database_id_field,profile%database_id,station)
360  profile_flag = profile%profile_flag
361  call mpp_write(unit,profile_flag_field,profile_flag,station)
362  profile_flag = profile%profile_flag_s
363  if (nvar_out .eq. 2) call mpp_write(unit,profile_flag_s_field,profile_flag,station)
364  call mpp_write(unit,lon_field,profile%lon,station)
365  call mpp_write(unit,lat_field,profile%lat,station)
366  call mpp_write(unit,time_field,days_since,station)
367  tmp_s = real(profile%yyyy)
368  call mpp_write(unit,yyyy_field,tmp_s,station)
369  tmp_s = real(profile%mmdd)
370  call mpp_write(unit,mmdd_field,tmp_s,station)
371  call mpp_write(unit,temp_err_field,profile%temp_err,station)
372  if (nvar_out .eq. 2) call mpp_write(unit,salt_err_field,profile%salt_err,station)
373 
374  if (profile%i_index .ne. -1.0 .and. profile%j_index .ne. -1.0) then
375  call mpp_write(unit, lon_index_field,profile%i_index)
376  call mpp_write(unit, lat_index_field,profile%j_index)
377  endif
378 
379  if (i .lt. nlinks) then
380  call mpp_write(unit,link_field,1.,station)
381  else
382  call mpp_write(unit,link_field,0.,station)
383  endif
384 
385 enddo
386 
387 end subroutine write_profile
388 
389 subroutine close_profile_file(unit)
391  integer, intent(in) :: unit
392 
393  call mpp_close(unit)
394 
395 end subroutine close_profile_file
396 
397 subroutine write_ocean_data_init()
399  module_is_initialized=.true.
400 
401  sta_num=0;unit_num=0;nfiles=0
402 
403  return
404 
405 end subroutine write_ocean_data_init
406 
407 end module write_ocean_data_mod
type(fieldtype), save probe_field
type(fieldtype), save ocn_vehicle_field
integer, parameter, public max_levels_file
Controls record length for optimal storage.
Definition: oda_types.F90:43
type(fieldtype), save lon_index_field
type(fieldtype), save mmdd_field
integer, dimension(max_files), save unit_num
integer, parameter ref_sec
type(fieldtype), save lat_field
integer, parameter ref_yr
integer function, public open_profile_file(name, nvar, grid_lon, grid_lat, thread, fset)
integer, parameter ref_hr
type(fieldtype), save profile_flag_s_field
type(fieldtype), save yyyy_field
type(fieldtype), save data_s_field
type(fieldtype), save link_field
Definition: mpp.F90:39
type(fieldtype), save nvar_field
integer, dimension(max_files), save sta_num
type(fieldtype), save lat_index_field
type(fieldtype), save salt_err_field
type(fieldtype), save project_field
type(fieldtype), save depth_field
integer, parameter ref_min
integer, parameter max_files
subroutine, public write_ocean_data_init()
subroutine, public write_profile(unit, profile)
type(fieldtype), save flag_t_field
type(fieldtype), save profile_flag_field
type(fieldtype), save flag_s_field
type(fieldtype), save data_t_field
type(fieldtype), save ref_inst_field
integer, parameter ref_mon
real, parameter, public missing_value
Definition: oda_types.F90:69
type(fieldtype), save fix_depth_field
subroutine, public close_profile_file(unit)
type(fieldtype), save lon_field
#define max(a, b)
Definition: mosaic_util.h:33
type(time_type) ref_time
#define min(a, b)
Definition: mosaic_util.h:32
subroutine, public get_time(Time, seconds, days, ticks, err_msg)
type(fieldtype), save temp_err_field
type(fieldtype), save time_field
type(fieldtype), save database_id_field
integer, parameter ref_day