21 #define _FLATTEN(A) reshape((A), (/size((A))/) ) 24 #include <fms_platform.h> 28 public :: cld_ntrp_linear_cell_interp, cld_ntrp_locate_cell, cld_ntrp_get_cell_values
29 #ifdef _TEST_CLOUD_INTERPOLATOR 30 public :: cld_ntrp_expand_index, cld_ntrp_contract_indices
34 #include<file_version.h> 35 real,
parameter ::
tol = 10.0*epsilon(1.)
40 _pure
subroutine cld_ntrp_expand_index(Ic, ie, ier)
41 integer,
intent(in) :: ic
42 integer,
intent(out) :: ie(:)
43 integer,
intent(out) :: ier
57 ie(j) = mod(ic/2**(j-1), 2)
60 end subroutine cld_ntrp_expand_index
64 _pure
subroutine cld_ntrp_contract_indices(ie, Ic, ier)
65 integer,
intent(in) :: ie(:)
66 integer,
intent(out) :: ic
67 integer,
intent(out) :: ier
80 if(ic >= 2**nd) ier = 1
82 end subroutine cld_ntrp_contract_indices
87 _pure
subroutine cld_ntrp_linear_cell_interp(fvals, ts, f, ier)
88 real,
intent(in) :: fvals(0:)
89 real,
intent(in) :: ts(:)
91 integer,
intent(out) :: ier
93 integer j, nd, ic, iflag
94 integer ie(
size(fvals))
100 if(
size(fvals) /= 2**nd)
then 107 call cld_ntrp_expand_index(ic, ie, iflag)
109 basis = basis * ( (1.0-
real(ie(j)))*(1.0-ts(j)) +
real(ie(j))*ts(j) )
111 f = f + fvals(ic)*basis
114 end subroutine cld_ntrp_linear_cell_interp
118 _pure
subroutine cld_ntrp_locate_cell(axis, x, index, ier)
119 real,
intent(in) :: axis(:)
120 real,
intent(in) :: x
121 integer,
intent(out) :: index
122 integer,
intent(out) :: ier
125 integer n, index1, is
126 real axis_1, axis_n, axis_min, axis_max
139 if(axis_1 > axis_n)
then 145 if(x < axis_min-
tol)
then 149 if(x > axis_max+
tol)
then 154 index = floor(
real(n-1)*(x - axis_1)/(axis_n-axis_1)) + 1
155 index =
min(n-1, index)
159 if(axis(index) <= x+
tol)
then 160 if(x <= axis(index1)+
tol)
then 168 if(axis(index1) >= x-
tol)
return 175 if(axis(index) <= x+
tol)
return 180 if(axis(index) >= x-
tol)
then 181 if(x >= axis(index1)-
tol)
then 189 if(axis(index1) <= x+
tol)
return 196 if(axis(index) >= x-
tol)
return 201 end subroutine cld_ntrp_locate_cell
205 _pure
subroutine cld_ntrp_get_flat_index(nsizes, indices, flat_index, ier)
206 integer,
intent(in) :: nsizes(:)
207 integer,
intent(in) :: indices(:)
208 integer,
intent(out) :: flat_index
209 integer,
intent(out) :: ier
216 if(nd /=
size(indices))
then 222 flat_index = indices(nd)-1
224 flat_index = flat_index*nsizes(id) + indices(id)-1
226 flat_index = flat_index + 1
228 end subroutine cld_ntrp_get_flat_index
232 _pure
subroutine cld_ntrp_get_cell_values(nsizes, fnodes, indices, fvals, ier)
233 integer,
intent(in) :: nsizes(:)
234 real,
intent(in) :: fnodes(:)
235 integer,
intent(in) :: indices(:)
236 real,
intent(out) :: fvals(0:)
237 integer,
intent(out) :: ier
239 integer id, nt, nd, flat_index, ic, iflag
240 integer,
dimension(size(nsizes)) :: cell_indices, node_indices
245 if(nd /=
size(indices))
then 250 if(2**nd >
size(fvals))
then 259 if(nt /=
size(fnodes))
then 266 call cld_ntrp_expand_index(ic, cell_indices, iflag)
267 node_indices = indices + cell_indices
268 call cld_ntrp_get_flat_index(nsizes, node_indices, flat_index, iflag)
269 fvals(ic) = fnodes(flat_index)
272 end subroutine cld_ntrp_get_cell_values
277 #ifdef _TEST_CLOUD_INTERPOLATOR 282 call test_expansion_contraction
283 call test_linear_cell_interpolation
284 call test_cell_search
285 call test_get_node_values
288 subroutine test_expansion_contraction
289 integer ie1(4), ie2(4), ic, ier, idiff, j
291 call cld_ntrp_contract_indices(ie1, ic, ier)
292 if(ier/=0) print *,
'ERROR flag ier=', ier
293 call cld_ntrp_expand_index(ic, ie2, ier)
294 if(ier/=0) print *,
'ERROR flag ier=', ier
297 idiff = idiff + abs(ie1(j)-ie2(j))
300 print *,
'ERROR: contraction/expansion test failed (ie1/=ie2)' 302 print *,
'ie1 = ', ie1
303 print *,
'ie2 = ', ie2
306 end subroutine test_expansion_contraction
308 subroutine test_linear_cell_interpolation
309 integer,
parameter :: nd = 3
310 real :: fvals(2**nd), ts(nd)
314 fvals = (/ 1., 2., 3., 4., 4., 5., 6., 7. /)
315 ts = (/ 0.1, 0.2, 0.3 /)
316 fx = 1. + ts(1) + 2*ts(2) + 3*ts(3)
317 call cld_ntrp_linear_cell_interp(fvals, ts, fi, ier)
318 if(ier/=0) print *,
'ERROR flag ier=', ier
319 print *,
'fi, fx = ', fi, fx
320 end subroutine test_linear_cell_interpolation
322 subroutine test_cell_search
324 integer,
parameter :: n = 5
325 real :: axis1(n) = (/0., 0.1, 0.2, 0.3, 0.4/)
326 real :: axis2(n) = (/0., 0.01, 0.02, 0.03, 0.4/)
327 real :: axis3(n) = (/0.4, 0.3, 0.2, 0.1, 0./)
328 real :: axis4(n) = (/0.4, 0.03, 0.02, 0.01, 0./)
330 integer :: ier_tot = 0
332 print *,
'axis1=', axis1
334 call cld_ntrp_locate_cell(axis1, x, index, ier)
335 print *,
' x=',x,
' index=', index,
' ==? ', -1
336 ier_tot = ier_tot + abs(index - (-1))
338 call cld_ntrp_locate_cell(axis1, x, index, ier)
339 print *,
' x=',x,
' index=', index,
' ==? ', 1
340 ier_tot = ier_tot + abs(index - (1))
342 call cld_ntrp_locate_cell(axis1, x, index, ier)
343 print *,
' x=',x,
' index=', index,
' ==? ', 2
344 ier_tot = ier_tot + abs(index - (2))
346 call cld_ntrp_locate_cell(axis1, x, index, ier)
347 print *,
' x=',x,
' index=', index,
' ==? ', 4
348 ier_tot = ier_tot + abs(index - (4))
350 call cld_ntrp_locate_cell(axis1, x, index, ier)
351 print *,
' x=',x,
' index=', index,
' ==? ', -1
352 ier_tot = ier_tot + abs(index - (-1))
354 print *,
'axis2=', axis1
356 call cld_ntrp_locate_cell(axis2, x, index, ier)
357 print *,
' x=',x,
' index=', index,
' ==? ', -1
358 ier_tot = ier_tot + abs(index - (-1))
360 call cld_ntrp_locate_cell(axis2, x, index, ier)
361 print *,
' x=',x,
' index=', index,
' ==? ', 1
362 ier_tot = ier_tot + abs(index - (1))
364 call cld_ntrp_locate_cell(axis2, x, index, ier)
365 print *,
' x=',x,
' index=', index,
' ==? ', 4
366 ier_tot = ier_tot + abs(index - (4))
368 call cld_ntrp_locate_cell(axis2, x, index, ier)
369 print *,
' x=',x,
' index=', index,
' ==? ', 4
370 ier_tot = ier_tot + abs(index - (4))
372 call cld_ntrp_locate_cell(axis2, x, index, ier)
373 print *,
' x=',x,
' index=', index,
' ==? ', -1
374 ier_tot = ier_tot + abs(index - (-1))
376 print *,
'axis3=', axis1
378 call cld_ntrp_locate_cell(axis3, x, index, ier)
379 print *,
' x=',x,
' index=', index,
' ==? ', -1
380 ier_tot = ier_tot + abs(index - (-1))
382 call cld_ntrp_locate_cell(axis3, x, index, ier)
383 print *,
' x=',x,
' index=', index,
' ==? ', 4
384 ier_tot = ier_tot + abs(index - (4))
386 call cld_ntrp_locate_cell(axis3, x, index, ier)
387 print *,
' x=',x,
' index=', index,
' ==? ', 4
388 ier_tot = ier_tot + abs(index - (4))
390 call cld_ntrp_locate_cell(axis3, x, index, ier)
391 print *,
' x=',x,
' index=', index,
' ==? ', 1
392 ier_tot = ier_tot + abs(index - (1))
394 call cld_ntrp_locate_cell(axis3, x, index, ier)
395 print *,
' x=',x,
' index=', index,
' ==? ', -1
396 ier_tot = ier_tot + abs(index - (-1))
398 print *,
'axis4=', axis1
400 call cld_ntrp_locate_cell(axis4, x, index, ier)
401 print *,
' x=',x,
' index=', index,
' ==? ', -1
402 ier_tot = ier_tot + abs(index - (-1))
404 call cld_ntrp_locate_cell(axis4, x, index, ier)
405 print *,
' x=',x,
' index=', index,
' ==? ', 4
406 ier_tot = ier_tot + abs(index - (4))
408 call cld_ntrp_locate_cell(axis4, x, index, ier)
409 print *,
' x=',x,
' index=', index,
' ==? ', 1
410 ier_tot = ier_tot + abs(index - (1))
412 call cld_ntrp_locate_cell(axis4, x, index, ier)
413 print *,
' x=',x,
' index=', index,
' ==? ', 1
414 ier_tot = ier_tot + abs(index - (1))
416 call cld_ntrp_locate_cell(axis4, x, index, ier)
417 print *,
' x=',x,
' index=', index,
' ==? ', -1
418 ier_tot = ier_tot + abs(index - (-1))
420 print *,
'Total error in test_cell_search: ', ier_tot
422 end subroutine test_cell_search
424 subroutine test_get_node_values
425 integer,
parameter :: nd = 3, n1=6, n2=5, n3=4
426 real,
dimension(n1, n2, n3) :: fnodes
427 real :: fvals(2**nd), fexact(2**nd)
429 integer i, j, k, ier, indices(nd)
430 real :: error_tot = 0.
434 x = 1*
real(i-1)/
real(n1-1)
435 y = 2*
real(j-1)/
real(n2-1)
436 z = 3*
real(k-1)/
real(n3-1)
437 fnodes(i,j,k) = x + y*z**2
443 call cld_ntrp_get_cell_values((/n1,n2,n3/), _flatten(fnodes), indices, fvals, ier)
444 fexact = (/0.0, 0.2, 0.0, 0.2, 0.0, 0.2, 0.5, 0.7/)
445 if(ier/=0) print *,
'ERROR flag ier=', ier
446 print *,
'indices ', indices
447 print *,
'fvals=', fvals,
' ==? ', fexact
448 error_tot = error_tot + abs(sum(fvals - fexact))
451 call cld_ntrp_get_cell_values((/n1,n2,n3/), _flatten(fnodes), indices, fvals, ier)
452 fexact = (/2.3, 2.5, 2.8, 3.0, 6.8, 7.0, 8.8, 9.0/)
453 if(ier/=0) print *,
'ERROR flag ier=', ier
454 print *,
'indices ', indices
455 print *,
'fvals=', fvals,
' ==? ', fexact
456 error_tot = error_tot + abs(sum(fvals - fexact))
458 print *,
'Total error in test_get_node_values: ', error_tot
461 end subroutine test_get_node_values
************************************************************************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)