libsim Versione 8.0.0

◆ grid_transform_levtype_levtype_init()

subroutine 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 )

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 1084 del file grid_transform_class.F90.

1086 trim(to_char(trans%vertint%input_levtype%level1))//','// &
1087 trim(to_char(trans%vertint%input_levtype%level2))// &
1088 ') suitable for interpolation')
1089 ENDIF
1090 IF (ostart == 0) THEN
1091 CALL l4f_category_log(this%category, l4f_warn, &
1092 'grid_transform_levtype_levtype_init: &
1093 &output contains no vertical levels of type ('// &
1094 trim(to_char(trans%vertint%output_levtype%level1))//','// &
1095 trim(to_char(trans%vertint%output_levtype%level2))// &
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
1152ENDIF
1153
1154END 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
1159SUBROUTINE make_vert_coord(lev, mask, coord, dolog)
1160TYPE(vol7d_level),INTENT(in) :: lev(:)
1161LOGICAL,INTENT(inout) :: mask(:)
1162DOUBLE PRECISION,INTENT(out) :: coord(:)
1163LOGICAL,INTENT(out) :: dolog
1164
1165INTEGER :: k
1166DOUBLE PRECISION :: fact
1167
1168dolog = .false.
1169k = firsttrue(mask)
1170IF (k <= 0) RETURN
1171coord(:) = dmiss
1172
1173IF (any(lev(k)%level1 == height_level)) THEN ! improve with a conversion table somewhere
1174 fact = 1.0d-3
1175ELSE IF (any(lev(k)%level1 == thermo_level)) THEN
1176 fact = 1.0d-1
1177ELSE IF (any(lev(k)%level1 == sigma_level)) THEN
1178 fact = 1.0d-4
1179ELSE
1180 fact = 1.0d0
1181ENDIF
1182
1183IF (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
1194ELSE ! 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
1205ENDIF
1206
1207! refine mask
1208mask(:) = mask(:) .AND. c_e(coord(:))
1209
1210END SUBROUTINE make_vert_coord
1211
1212
1213!> Constructor for a \a grid_transform object, defining a particular
1214!! grid-to-grid transformation. It defines an object describing a
1215!! transformation from one rectangular grid to another; the abstract
1216!! type of transformation is described in the transformation object \a
1217!! trans (type transform_def) which must have been properly
1218!! initialised. The additional information required here is the
1219!! description of the input grid \a in (type griddim_def), the
1220!! description of the output grid \a out (type griddim_def as
1221!! well). The description of the output grid must be initialized for
1222!! interpolating type transformations ('inter' and 'boxinter'), while
1223!! it is generated by this constructor and returned in output for
1224!! 'zoom', 'boxregrid', 'maskgen' and 'polyinter' transformations.
1225!!
1226!! The generated \a grid_transform object is specific to the input and
1227!! output grids involved. The function \a c_e can be used in order to
1228!! check whether the object has been successfully initialised, if the
1229!! result is \a .FALSE., it should not be used further on.
1230SUBROUTINE grid_transform_init(this, trans, in, out, maskgrid, maskbounds, &
1231 categoryappend)
1232TYPE(grid_transform),INTENT(out) :: this !< grid_transformation object
1233TYPE(transform_def),INTENT(in) :: trans !< transformation object
1234TYPE(griddim_def),INTENT(inout) :: in !< griddim object to transform
1235TYPE(griddim_def),INTENT(inout) :: out !< griddim object defining target grid (input or output depending on type of transformation)
1236REAL,INTENT(in),OPTIONAL :: maskgrid(:,:) !< 2D field to be used for defining valid points, it must have the same shape as the field to be interpolated (for transformation type 'metamorphosis:maskvalid')
1237REAL,INTENT(in),OPTIONAL :: maskbounds(:) !< array of boundary values for defining a subset of valid points where the values of \a maskgrid are within the first and last value of \a maskbounds (for transformation type 'metamorphosis:maskvalid/settoinvalid' and others)
1238CHARACTER(len=*),INTENT(in),OPTIONAL :: categoryappend !< append this suffix to log4fortran namespace category
1239
1240INTEGER :: nx, ny, i, j, ix, iy, n, nm, nr, cf_i, cf_o, nprev, &
1241 xnmin, xnmax, ynmin, ynmax
1242DOUBLE PRECISION :: xmin, xmax, ymin, ymax, steplon, steplat, &
1243 xmin_new, ymin_new, ellips_smaj_axis, ellips_flatt, r2
1244TYPE(geo_proj) :: proj_in, proj_out
1245TYPE(georef_coord) :: point
1246LOGICAL,ALLOCATABLE :: point_mask(:,:)
1247TYPE(griddim_def) :: lin, lout
1248
1249
1250CALL grid_transform_init_common(this, trans, categoryappend)
1251#ifdef DEBUG
1252CALL 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)
1256CALL get_val(in, ellips_smaj_axis=ellips_smaj_axis, ellips_flatt=ellips_flatt)
1257CALL set_val(out, ellips_smaj_axis=ellips_smaj_axis, ellips_flatt=ellips_flatt)
1258
1259IF (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

Generated with Doxygen.