libsim  Versione8.0.0

◆ grid_transform_levtype_levtype_init()

subroutine grid_transform_class::grid_transform_levtype_levtype_init ( type(grid_transform), intent(out)  this,
type(transform_def), intent(in)  trans,
type(vol7d_level), dimension(:), intent(in)  lev_in,
type(vol7d_level), dimension(:), intent(in)  lev_out,
real, dimension(:,:,:), intent(inout), optional, allocatable  coord_3d_in,
character(len=*), intent(in), optional  categoryappend 
)
private

Constructor for a grid_transform object, defining a particular vertical transformation.

It defines an object describing a transformation involving operations on the vertical direction only, thus it applies in the same way to grid-to-grid and to sparse points-to-sparse points transformations; the abstract type of the transformation is described in the transformation object trans (type transform_def) which must have been properly initialised. The additional information required here is the list of input and output levels and an optional 3-d field indicating the vertical coordinates of the input dataset.

The input level list lev_in is a 1-d array of vol7d_level type, describing the vertical coordinate system of the whole input dataset, only the vertical levels or layers matching the level type indicated when initialising the transformation object trans will be used, the others will be discarded in the vertical transformation. However the relevant vertical levels must be contiguous and sorted accordingly to the default vol7d_level sort order. The argument lev_out describes the vertical coordinate system of the output dataset. A particular case to be considered is when SIZE(lev_out)==0, this means that the output coordinates have to be computed automatically in the current subroutine, this is supported only for hybrid levels/layers.

When the input and output level types are different, the coord_3d_in array must be provided, indicating the vertical coordinate of every input grid point expressed in terms of the output vertical coordinate system (e.g. height if interpolating to constant height levels or pressure if interpolating to isobaric levels). This array must contain, in the 3rd vertical dimension, only the those levels/layers of lev_in that are actually used for interpolation. The storage space of coord_3d_in is "stolen" by this method, so the array will appear as unallocated and unusable to the calling procedure after return from this subroutine.

Layers in the grib2 sense (i.e. layers between two surfaces) can be handled by this class only when the upper and lower surfaces are of the same type; in these cases the coordinate assigned to every layer fro interpolation is the average (or log-average in case of isobaric surfaces) between the coordinates of the corresponding upper and lower surfaces.

Parametri
[out]thisgrid_transformation object
[in]transtransformation object
[in]lev_invol7d_level from input object
[in]lev_outvol7d_level object defining target vertical grid
[in,out]coord_3d_invertical coordinates of each input point in target reference system
[in]categoryappendappend this suffix to log4fortran namespace category

Definizione alla linea 1096 del file grid_transform_class.F90.

1096  ') suitable for interpolation')
1097  RETURN
1098 ! oend = -1 ! for loops
1099  ENDIF
1100 
1101 ! end of code common for all vertint subtypes
1102  IF (this%trans%sub_type == 'linear') THEN
1103 
1104  ALLOCATE(this%inter_index_z(this%outnz), this%inter_zp(this%outnz))
1105  this%inter_index_z(:) = imiss
1106  this%inter_zp(:) = dmiss
1107  IF (this%trans%extrap .AND. istart > 0) THEN
1108  WHERE(mask_out)
1109 ! extrapolate down by default
1110  this%inter_index_z(:) = istart
1111  this%inter_zp(:) = 1.0d0
1112  ENDWHERE
1113  ENDIF
1114 
1115  icache = istart + 1
1116  outlev: DO j = ostart, oend
1117  inlev: DO i = icache, iend
1118  IF (coord_in(i) >= coord_out(j)) THEN
1119  IF (coord_out(j) >= coord_in(i-1)) THEN
1120  this%inter_index_z(j) = i - 1
1121  this%inter_zp(j) = (coord_out(j)-coord_in(i-1)) / &
1122  (coord_in(i)-coord_in(i-1)) ! weight for (i)
1123  icache = i ! speedup next j iteration
1124  ENDIF
1125  cycle outlev ! found or extrapolated down
1126  ENDIF
1127  ENDDO inlev
1128 ! if I'm here I must extrapolate up
1129  IF (this%trans%extrap .AND. iend > 1) THEN
1130  this%inter_index_z(j) = iend - 1
1131  this%inter_zp(j) = 0.0d0
1132  ENDIF
1133  ENDDO outlev
1134 
1135  DEALLOCATE(coord_out, mask_out)
1136  this%valid = .true.
1137 
1138  ELSE IF (this%trans%sub_type == 'linearsparse') THEN
1139 ! just store vertical coordinates, dirty work is done later
1140  ALLOCATE(this%vcoord_in(this%levused), this%vcoord_out(SIZE(coord_out)))
1141  this%vcoord_in(:) = coord_in(this%levshift+1:this%levshift+this%levused)
1142  this%vcoord_out(:) = coord_out(:)
1143  DEALLOCATE(coord_out, mask_out)
1144  this%valid = .true.
1145 
1146  ENDIF
1147 
1148  ENDIF ! levels are different
1149 
1150 !ELSE IF (this%trans%trans_type == 'verttrans') THEN
1151 
1152 ENDIF
1153 
1154 END SUBROUTINE grid_transform_levtype_levtype_init
1155 
1156 
1157 ! internal subroutine for computing vertical coordinate values, for
1158 ! pressure-based coordinates the logarithm is computed
1159 SUBROUTINE make_vert_coord(lev, mask, coord, dolog)
1160 TYPE(vol7d_level),INTENT(in) :: lev(:)
1161 LOGICAL,INTENT(inout) :: mask(:)
1162 DOUBLE PRECISION,INTENT(out) :: coord(:)
1163 LOGICAL,INTENT(out) :: dolog
1164 
1165 INTEGER :: k
1166 DOUBLE PRECISION :: fact
1167 
1168 dolog = .false.
1169 k = firsttrue(mask)
1170 IF (k <= 0) RETURN
1171 coord(:) = dmiss
1172 
1173 IF (any(lev(k)%level1 == height_level)) THEN ! improve with a conversion table somewhere
1174  fact = 1.0d-3
1175 ELSE IF (any(lev(k)%level1 == thermo_level)) THEN
1176  fact = 1.0d-1
1177 ELSE IF (any(lev(k)%level1 == sigma_level)) THEN
1178  fact = 1.0d-4
1179 ELSE
1180  fact = 1.0d0
1181 ENDIF
1182 
1183 IF (c_e(lev(k)%level2) .AND. lev(k)%level1 == lev(k)%level2) THEN ! layer between 2 levels
1184  IF (lev(k)%level1 == 100 .OR. lev(k)%level1 == 108) THEN ! pressure, compute log
1185  WHERE(mask(:) .AND. lev(:)%l1 > 0 .AND. lev(:)%l2 > 0)
1186  coord(:) = (log(dble(lev(:)%l1)*fact) + log(dble(lev(:)%l2)*fact))*0.5d0
1187  END WHERE
1188  dolog = .true.
1189  ELSE
1190  WHERE(mask(:))
1191  coord(:) = (lev(:)%l1 + lev(:)%l2)*fact*0.5d0
1192  END WHERE
1193  ENDIF
1194 ELSE ! half level
1195  IF (lev(k)%level1 == 100 .OR. lev(k)%level1 == 108) THEN ! pressure, compute log
1196  WHERE(mask(:) .AND. lev(:)%l1 > 0)
1197  coord(:) = log(dble(lev(:)%l1)*fact)
1198  END WHERE
1199  dolog = .true.
1200  ELSE
1201  WHERE(mask(:))
1202  coord(:) = lev(:)%l1*fact
1203  END WHERE
1204  ENDIF
1205 ENDIF
1206 
1207 ! refine mask
1208 mask(:) = mask(:) .AND. c_e(coord(:))
1209 
1210 END SUBROUTINE make_vert_coord
1211 
1212 
1230 SUBROUTINE grid_transform_init(this, trans, in, out, maskgrid, maskbounds, &
1231  categoryappend)
1232 TYPE(grid_transform),INTENT(out) :: this
1233 TYPE(transform_def),INTENT(in) :: trans
1234 TYPE(griddim_def),INTENT(inout) :: in
1235 TYPE(griddim_def),INTENT(inout) :: out
1236 REAL,INTENT(in),OPTIONAL :: maskgrid(:,:)
1237 REAL,INTENT(in),OPTIONAL :: maskbounds(:)
1238 CHARACTER(len=*),INTENT(in),OPTIONAL :: categoryappend
1239 
1240 INTEGER :: nx, ny, i, j, ix, iy, n, nm, nr, cf_i, cf_o, nprev, &
1241  xnmin, xnmax, ynmin, ynmax
1242 DOUBLE PRECISION :: xmin, xmax, ymin, ymax, steplon, steplat, &
1243  xmin_new, ymin_new, ellips_smaj_axis, ellips_flatt, r2
1244 TYPE(geo_proj) :: proj_in, proj_out
1245 TYPE(georef_coord) :: point
1246 LOGICAL,ALLOCATABLE :: point_mask(:,:)
1247 TYPE(griddim_def) :: lin, lout
1248 
1249 
1250 CALL grid_transform_init_common(this, trans, categoryappend)
1251 #ifdef DEBUG
1252 CALL l4f_category_log(this%category, l4f_debug, "grid_transform vg6d-vg6d")
1253 #endif
1254 
1255 ! output ellipsoid has to be the same as for the input (improve)
1256 CALL get_val(in, ellips_smaj_axis=ellips_smaj_axis, ellips_flatt=ellips_flatt)
1257 CALL set_val(out, ellips_smaj_axis=ellips_smaj_axis, ellips_flatt=ellips_flatt)
1258 
1259 IF (this%trans%trans_type == 'zoom') THEN
1260 
1261  IF (this%trans%sub_type == 'coord') THEN
1262 
1263  CALL griddim_zoom_coord(in, &
1264  this%trans%rect_coo%ilon, this%trans%rect_coo%ilat,&
1265  this%trans%rect_coo%flon, this%trans%rect_coo%flat,&
1266  this%trans%rect_ind%ix, this%trans%rect_ind%iy, &
1267  this%trans%rect_ind%fx, this%trans%rect_ind%fy)
1268 
1269  ELSE IF (this%trans%sub_type == 'projcoord') THEN
1270 
1271  CALL griddim_zoom_projcoord(in, &
1272  this%trans%rect_coo%ilon, this%trans%rect_coo%ilat,&
1273  this%trans%rect_coo%flon, this%trans%rect_coo%flat,&
1274  this%trans%rect_ind%ix, this%trans%rect_ind%iy, &
1275  this%trans%rect_ind%fx, this%trans%rect_ind%fy)
1276 
1277  ELSE IF (this%trans%sub_type == 'coordbb') THEN
1278 
1279 ! compute coordinates of input grid in geo system
1280  CALL copy(in, lin)
1281  CALL unproj(lin)
1282  CALL get_val(lin, nx=nx, ny=ny)
1283 
1284  ALLOCATE(point_mask(nx,ny))
1285  point_mask(:,:) = .false.
1286 
1287 ! mark points falling into requested bounding-box
1288  DO j = 1, ny
1289  DO i = 1, nx
1290 ! IF (geo_coord_inside_rectang())
1291  IF (lin%dim%lon(i,j) > this%trans%rect_coo%ilon .AND. &
1292  lin%dim%lon(i,j) < this%trans%rect_coo%flon .AND. &
1293  lin%dim%lat(i,j) > this%trans%rect_coo%ilat .AND. &
1294  lin%dim%lat(i,j) < this%trans%rect_coo%flat) THEN ! improve!
1295  point_mask(i,j) = .true.
1296  ENDIF
1297  ENDDO
1298  ENDDO
1299 
1300 ! determine cut indices keeping all points which fall inside b-b
1301  DO i = 1, nx
1302  IF (any(point_mask(i,:))) EXIT
1303  ENDDO
1304  this%trans%rect_ind%ix = i
1305  DO i = nx, this%trans%rect_ind%ix, -1
1306  IF (any(point_mask(i,:))) EXIT
1307  ENDDO
1308  this%trans%rect_ind%fx = i
1309 
1310  DO j = 1, ny
1311  IF (any(point_mask(:,j))) EXIT
1312  ENDDO
1313  this%trans%rect_ind%iy = j
1314  DO j = ny, this%trans%rect_ind%iy, -1
1315  IF (any(point_mask(:,j))) EXIT
1316  ENDDO
1317  this%trans%rect_ind%fy = j
1318 
1319  DEALLOCATE(point_mask)
1320 
1321  IF (this%trans%rect_ind%ix > this%trans%rect_ind%fx .OR. &
1322  this%trans%rect_ind%iy > this%trans%rect_ind%fy) THEN
1323 
1324  CALL l4f_category_log(this%category,l4f_error, &
1325  "zoom coordbb: no points inside bounding box "//&
1326  trim(to_char(this%trans%rect_coo%ilon))//","// &
1327  trim(to_char(this%trans%rect_coo%flon))//","// &
1328  trim(to_char(this%trans%rect_coo%ilat))//","// &
1329  trim(to_char(this%trans%rect_coo%flat)))
1330  CALL raise_error()
1331  RETURN
1332 
1333  ENDIF
1334  CALL delete(lin)
1335  ENDIF
1336 ! to do in all zoom cases
1337 
1338  CALL get_val(in, nx=nx, ny=ny, xmin=xmin, xmax=xmax, &
1339  ymin=ymin, ymax=ymax, dx=steplon, dy=steplat)
1340 
1341 ! old indices
1342  this%iniox = min(max(this%trans%rect_ind%ix,1),nx) ! iox
1343  this%inioy = min(max(this%trans%rect_ind%iy,1),ny) ! ioy
1344  this%infox = max(min(this%trans%rect_ind%fx,nx),1) ! fox
1345  this%infoy = max(min(this%trans%rect_ind%fy,ny),1) ! foy
1346 ! new indices
1347  this%outinx = min(max(2-this%trans%rect_ind%ix,1),nx) ! inx
1348  this%outiny = min(max(2-this%trans%rect_ind%iy,1),ny) ! iny
1349  this%outfnx = min(this%trans%rect_ind%fx,nx)-this%trans%rect_ind%ix+1 ! fnx
1350  this%outfny = min(this%trans%rect_ind%fy,ny)-this%trans%rect_ind%iy+1 ! fny
1351 

Generated with Doxygen.