19 use odb_c_binding,
only: &
27 use odbql_wrappers,
only: &
40 use,
intrinsic :: iso_c_binding, only: &
46 character(len=1000) :: filename
47 character(len=1000) :: output_filename
50 character(len=7000) :: messages(4)
51 real,
allocatable :: latitudes(:)
52 real,
allocatable :: longitudes(:)
53 real,
allocatable :: times_netcdf(:)
54 real,
allocatable :: observations(:)
55 real,
allocatable :: pressures(:)
56 integer,
allocatable :: times(:)
57 integer,
allocatable :: dates(:)
59 integer(kind=c_int) :: odb_rc
60 character(len=*),
parameter :: odb_column_names(9) = [character(len=18) ::
"seqno",
"lat",
"lon",
"entryno", &
61 "date",
"time",
"varno",
"vertco_reference_1",
"obsvalue"]
62 integer :: odb_column_types(9) = [odb_integer, odb_real, odb_real, odb_integer, odb_integer, &
63 odb_integer, odb_integer, odb_real, odb_real]
64 character(len=5000) :: create_table_sql_string
65 character(len=5000) :: insert_into_sql_string
66 character(len=5000) :: unparsed_sql
67 type(odbql_stmt) :: stmt
68 integer(kind=c_int) :: col_name_index
70 real(kind=c_double) :: buffer(
size(odb_column_names))
73 character(len=2000) :: arguments(2)
75 call get_command_argument (1, filename)
76 call get_command_argument (2, output_filename)
78 if (filename ==
"" .or. output_filename ==
"")
then 79 write (messages(1),
'(a,i0)')
"Please provide two arguments, input-filename output-filename" 80 call fail (messages(1:1))
83 rc = nf90_open(filename, nf90_nowrite, file_id)
84 if (rc /= nf90_noerr)
then 85 write (messages(1),
'(a,i0)')
"nf90_open failed with rc = ", rc
86 write (messages(2),
'(2a)')
"file name = ", trim(filename)
87 messages(3) = nf90_strerror(rc)
88 call fail (messages(1:3))
95 allocate (times(
size(times_netcdf)))
96 allocate (dates(
size(times_netcdf)))
98 rc = nf90_get_att(file_id, nf90_global,
"date_time", date_time)
99 if (rc /= nf90_noerr)
then 100 write (messages(1),
'(a,i0)')
"nf90_get_at failed for date_time with rc = ", rc
101 write (messages(2),
'(a,i0)')
"file id = ", file_id
102 messages(3) = nf90_strerror(rc)
103 call fail (messages(1:3))
106 dates = date_time / 100
107 times = (date_time - (date_time / 100) * 100) * 10000
108 times = times + 10000 * int(times_netcdf)
109 times_netcdf = times_netcdf - int(times_netcdf)
110 where (times_netcdf >= 0)
111 times = times + nint(60 * times_netcdf) * 100
113 times = times - 10000
114 times = times + nint(60 * (1 - abs(times_netcdf))) * 100
120 rc = nf90_close(file_id)
121 if (rc /= nf90_noerr)
then 122 write (messages(1),
'(a,i0)')
"nf90_close failed with rc = ", rc
123 write (messages(2),
'(a,i0)')
"file id = ", file_id
124 messages(3) = nf90_strerror(rc)
125 call fail (messages(1:3))
128 call odbql_open (
"", odb, odb_rc)
129 if (odb_rc /= 0)
then 130 write (messages(1),
'(a,i0)')
"odbql_open failed with rc = ", odb_rc
131 call fail (messages(1:1))
134 call create_table_sql (odb_column_names, odb_column_types, output_filename, create_table_sql_string)
136 call odbql_prepare_v2 (odb, trim(create_table_sql_string), -1_c_int, stmt, unparsed_sql, odb_rc)
137 if (odb_rc /= 0)
then 138 write (messages(1),
'(a,i0)')
"odbql_prepare_v2 failed (create table), rc = ", odb_rc
139 messages(2) = create_table_sql_string
140 call fail (messages(1:2))
145 call odbql_prepare_v2 (odb, trim(insert_into_sql_string), -1_c_int, stmt, unparsed_sql, odb_rc)
146 if (odb_rc /= 0)
then 147 write (messages(1),
'(a,i0)')
"odbql_prepare_v2 failed (insert into), rc = ", odb_rc
148 messages(2) = insert_into_sql_string
149 call fail (messages(1:2))
152 do iob = 1,
size(latitudes)
154 buffer(2) = latitudes(iob)
155 buffer(3) = longitudes(iob)
156 buffer(5) = dates(iob)
157 buffer(6) = times(iob)
160 buffer(8) = pressures(iob)
161 buffer(9) = observations(iob)
162 do col_name_index = 1,
size (odb_column_names)
163 select case (odb_column_types(col_name_index))
165 call odbql_bind_double (stmt, col_name_index, buffer(col_name_index))
167 call odbql_bind_int (stmt, col_name_index, nint(buffer(col_name_index), kind = c_int))
170 call odbql_step (stmt)
173 call odbql_finalize (stmt)
175 call odbql_close (odb)
179 subroutine fail (messages)
181 character(len=*),
intent(in) :: messages(:)
185 do i = 1,
size(messages)
186 write (0,
'(a)') trim(messages(i))
187 write (*,
'(a)') trim(messages(i))
198 nf90_inquire_dimension, &
199 nf90_inquire_variable, &
203 integer,
intent(in) :: file_id
204 character(len=*),
intent(in) :: var_name
205 real,
allocatable,
intent(out) :: output_array(:)
207 integer :: var_id, rc, ndims, length, dimids(1)
208 character(len=7000) :: messages(5)
210 rc = nf90_inq_varid(file_id, var_name, var_id)
211 if (rc /= nf90_noerr)
then 212 write (messages(1),
'(a,i0)')
"nf90_inq_varid failed for " // trim(var_name) //
" with rc = ", rc
213 write (messages(2),
'(a,i0)')
"file id = ", file_id
214 messages(3) = nf90_strerror(rc)
215 call fail (messages(1:3))
218 rc = nf90_inquire_variable(file_id, var_id, ndims = ndims, dimids = dimids)
219 if (rc /= nf90_noerr)
then 220 write (messages(1),
'(a,i0)')
"nf90_inquire_variable failed for " // trim(var_name) //
" with rc = ", rc
221 write (messages(2),
'(a,i0)')
"file id = ", file_id
222 write (messages(3),
'(a,i0)')
"var id = ", var_id
223 messages(4) = nf90_strerror(rc)
224 call fail (messages(1:4))
228 write (messages(1),
'(a,i0)')
"Should be a 1d arrays for " // trim(var_name)
229 write (messages(2),
'(a,i0,a)')
"Actually got ", ndims,
"d array" 230 write (messages(3),
'(a,i0)')
"file id = ", file_id
231 write (messages(4),
'(a,i0)')
"var id = ", var_id
232 call fail (messages(1:4))
235 rc = nf90_inquire_dimension(file_id, dimids(1), len = length)
236 if (rc /= nf90_noerr)
then 237 write (messages(1),
'(a,i0)')
"nf90_inquire_dimension failed for " // trim(var_name) //
" with rc = ", rc
238 write (messages(2),
'(a,i0)')
"file id = ", file_id
239 write (messages(3),
'(a,i0)')
"var id = ", var_id
240 write (messages(4),
'(a,i0)')
"dim id = ", dimids(1)
241 messages(5) = nf90_strerror(rc)
242 call fail (messages(1:5))
245 allocate (output_array(length))
247 rc = nf90_get_var(file_id, var_id, output_array)
248 if (rc /= nf90_noerr)
then 249 write (messages(1),
'(a,i0)')
"nf90_get_var failed for " // trim(var_name) //
" with rc = ", rc
250 write (messages(2),
'(a,i0)')
"file id = ", file_id
251 write (messages(2),
'(a,i0)')
"var id = ", var_id
252 messages(4) = nf90_strerror(rc)
253 call fail (messages(1:4))
subroutine insert_into_sql(column_names, sql)
subroutine get_netcdf_array(file_id, var_name, output_array)
subroutine fail(messages)
Fortran module with ODB API utility routines.
program netcdf_to_odb2
Fortran program to convert the existing NetCDF file into an ODB-2.
subroutine create_table_sql(column_names, column_types, filename, sql)
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this ! since that attempts to gather all data on PE size(field%axes(:)) axsiz(i)