229 CHARACTER(len=255),
PARAMETER:: subcategory=
"grid_transform_class" 233 double precision :: boxdx
234 double precision :: boxdy
235 double precision :: radius
240 DOUBLE PRECISION :: percentile
249 END TYPE interval_info
281 TYPE(vol7d_level) :: input_levtype
282 TYPE(vol7d_var) :: input_coordvar
283 TYPE(vol7d_level) :: output_levtype
293 CHARACTER(len=80) :: trans_type
294 CHARACTER(len=80) :: sub_type
296 TYPE(rect_ind) :: rect_ind
297 TYPE(rect_coo) :: rect_coo
298 TYPE(area_info) :: area_info
299 TYPE(arrayof_georef_coord_array) :: poly
300 TYPE(stat_info) :: stat_info
301 TYPE(interval_info) :: interval_info
302 TYPE(box_info) :: box_info
303 TYPE(vertint) :: vertint
304 INTEGER :: time_definition
305 TYPE(l4f_handle) :: category
317 TYPE(transform_def),
PUBLIC :: trans
318 INTEGER :: innx = imiss
319 INTEGER :: inny = imiss
320 INTEGER :: innz = imiss
321 INTEGER :: outnx = imiss
322 INTEGER :: outny = imiss
323 INTEGER :: outnz = imiss
324 INTEGER :: levshift = imiss
325 INTEGER :: levused = imiss
326 INTEGER :: iniox,inioy,infox,infoy,outinx,outiny,outfnx,outfny
327 INTEGER,
POINTER :: inter_index_x(:,:) => null()
328 INTEGER,
POINTER :: inter_index_y(:,:) => null()
329 INTEGER,
POINTER :: inter_index_z(:) => null()
330 INTEGER,
POINTER :: point_index(:,:) => null()
331 DOUBLE PRECISION,
POINTER :: inter_x(:,:) => null()
332 DOUBLE PRECISION,
POINTER :: inter_y(:,:) => null()
333 DOUBLE PRECISION,
POINTER :: inter_xp(:,:) => null()
334 DOUBLE PRECISION,
POINTER :: inter_yp(:,:) => null()
335 DOUBLE PRECISION,
POINTER :: inter_zp(:) => null()
336 DOUBLE PRECISION,
POINTER :: vcoord_in(:) => null()
337 DOUBLE PRECISION,
POINTER :: vcoord_out(:) => null()
338 LOGICAL,
POINTER :: point_mask(:,:) => null()
339 LOGICAL,
POINTER :: stencil(:,:) => null()
340 REAL,
ALLOCATABLE :: coord_3d_in(:,:,:)
341 REAL,
ALLOCATABLE :: val_mask(:,:)
344 LOGICAL :: recur = .false.
345 LOGICAL :: dolog = .false.
349 TYPE(vol7d_level),
POINTER :: output_level_auto(:) => null()
350 TYPE(l4f_handle) :: category
351 LOGICAL :: valid = .false.
352 PROCEDURE(basic_find_index),
NOPASS,
POINTER :: find_index => basic_find_index
358 MODULE PROCEDURE transform_init, grid_transform_levtype_levtype_init, &
359 grid_transform_init, &
360 grid_transform_grid_vol7d_init, grid_transform_vol7d_grid_init, &
361 grid_transform_vol7d_vol7d_init
366 MODULE PROCEDURE transform_delete, grid_transform_delete
371 MODULE PROCEDURE transform_get_val, grid_transform_get_val
377 MODULE PROCEDURE grid_transform_compute, grid_transform_v7d_grid_compute
383 MODULE PROCEDURE grid_transform_c_e
389 PUBLIC interval_info, interval_info_new, interval_info_valid, basic_find_index
394 FUNCTION interval_info_new(interv_gt, interv_ge, interv_lt, interv_le)
RESULT(this)
395 REAL,
INTENT(in),
OPTIONAL :: interv_gt
396 REAL,
INTENT(in),
OPTIONAL :: interv_ge
397 REAL,
INTENT(in),
OPTIONAL :: interv_lt
398 REAL,
INTENT(in),
OPTIONAL :: interv_le
400 TYPE(interval_info) :: this
402 IF (
PRESENT(interv_gt))
THEN 403 IF (
c_e(interv_gt))
THEN 408 IF (
PRESENT(interv_ge))
THEN 409 IF (
c_e(interv_ge))
THEN 414 IF (
PRESENT(interv_lt))
THEN 415 IF (
c_e(interv_lt))
THEN 420 IF (
PRESENT(interv_le))
THEN 421 IF (
c_e(interv_le))
THEN 427 END FUNCTION interval_info_new
434 ELEMENTAL FUNCTION interval_info_valid(this, val)
435 TYPE(interval_info),
INTENT(in) :: this
436 REAL,
INTENT(in) :: val
438 REAL :: interval_info_valid
440 interval_info_valid = 1.0
442 IF (
c_e(this%gt))
THEN 443 IF (val < this%gt) interval_info_valid = 0.0
444 IF (.NOT.this%ge)
THEN 445 IF (val == this%gt) interval_info_valid = 0.0
448 IF (
c_e(this%lt))
THEN 449 IF (val > this%lt) interval_info_valid = 0.0
450 IF (.NOT.this%le)
THEN 451 IF (val == this%lt) interval_info_valid = 0.0
455 END FUNCTION interval_info_valid
463 SUBROUTINE transform_init(this, trans_type, sub_type, &
464 ix, iy, fx, fy, ilon, ilat, flon, flat, &
465 npx, npy, boxdx, boxdy, radius, poly, percentile, &
466 interv_gt, interv_ge, interv_lt, interv_le, &
467 extrap, time_definition, &
468 input_levtype, input_coordvar, output_levtype, categoryappend)
469 TYPE(transform_def),
INTENT(out) :: this
470 CHARACTER(len=*) :: trans_type
471 CHARACTER(len=*) :: sub_type
472 INTEGER,
INTENT(in),
OPTIONAL :: ix
473 INTEGER,
INTENT(in),
OPTIONAL :: iy
474 INTEGER,
INTENT(in),
OPTIONAL :: fx
475 INTEGER,
INTENT(in),
OPTIONAL :: fy
476 DOUBLEPRECISION,
INTENT(in),
OPTIONAL :: ilon
477 DOUBLEPRECISION,
INTENT(in),
OPTIONAL :: ilat
478 DOUBLEPRECISION,
INTENT(in),
OPTIONAL :: flon
479 DOUBLEPRECISION,
INTENT(in),
OPTIONAL :: flat
480 INTEGER,
INTENT(IN),
OPTIONAL :: npx
481 INTEGER,
INTENT(IN),
OPTIONAL :: npy
482 DOUBLEPRECISION,
INTENT(in),
OPTIONAL :: boxdx
483 DOUBLEPRECISION,
INTENT(in),
OPTIONAL :: boxdy
484 DOUBLEPRECISION,
INTENT(in),
OPTIONAL :: radius
485 TYPE(arrayof_georef_coord_array),
OPTIONAL :: poly
486 DOUBLEPRECISION,
INTENT(in),
OPTIONAL :: percentile
487 REAL,
INTENT(in),
OPTIONAL :: interv_gt
488 REAL,
INTENT(in),
OPTIONAL :: interv_ge
489 REAL,
INTENT(in),
OPTIONAL :: interv_lt
490 REAL,
INTENT(in),
OPTIONAL :: interv_le
491 LOGICAL,
INTENT(IN),
OPTIONAL :: extrap
492 INTEGER,
INTENT(IN),
OPTIONAL :: time_definition
493 TYPE(vol7d_level),
INTENT(IN),
OPTIONAL :: input_levtype
494 TYPE(vol7d_var),
INTENT(IN),
OPTIONAL :: input_coordvar
495 TYPE(vol7d_level),
INTENT(IN),
OPTIONAL :: output_levtype
496 character(len=*),
INTENT(in),
OPTIONAL :: categoryappend
498 character(len=512) :: a_name
500 IF (
PRESENT(categoryappend))
THEN 501 CALL l4f_launcher(a_name,a_name_append=trim(subcategory)//
"."// &
502 trim(categoryappend))
504 CALL l4f_launcher(a_name,a_name_append=trim(subcategory))
506 this%category=l4f_category_get_handle(a_name)
508 this%trans_type = trans_type
509 this%sub_type = sub_type
511 CALL optio(extrap,this%extrap)
514 call optio(iy,this%rect_ind%iy)
515 call optio(fx,this%rect_ind%fx)
516 call optio(fy,this%rect_ind%fy)
518 call optio(ilon,this%rect_coo%ilon)
519 call optio(ilat,this%rect_coo%ilat)
520 call optio(flon,this%rect_coo%flon)
521 call optio(flat,this%rect_coo%flat)
523 CALL optio(boxdx,this%area_info%boxdx)
524 CALL optio(boxdy,this%area_info%boxdy)
525 CALL optio(radius,this%area_info%radius)
526 IF (
PRESENT(poly)) this%poly = poly
527 CALL optio(percentile,this%stat_info%percentile)
529 this%interval_info = interval_info_new(interv_gt, interv_ge, interv_lt, interv_le)
531 CALL optio(npx,this%box_info%npx)
532 CALL optio(npy,this%box_info%npy)
534 IF (
PRESENT(input_levtype))
THEN 535 this%vertint%input_levtype = input_levtype
537 this%vertint%input_levtype = vol7d_level_miss
539 IF (
PRESENT(input_coordvar))
THEN 540 this%vertint%input_coordvar = input_coordvar
542 this%vertint%input_coordvar = vol7d_var_miss
544 IF (
PRESENT(output_levtype))
THEN 545 this%vertint%output_levtype = output_levtype
547 this%vertint%output_levtype = vol7d_level_miss
550 call optio(time_definition,this%time_definition)
551 if (
c_e(this%time_definition) .and. &
552 (this%time_definition < 0 .OR. this%time_definition > 2))
THEN 553 call l4f_category_log(this%category,l4f_error,
"Error time_definition invalid: "//
to_char(this%time_definition))
554 call raise_fatal_error()
558 IF (this%trans_type ==
'zoom')
THEN 560 IF (this%sub_type ==
'coord' .OR. this%sub_type ==
'projcoord')
THEN 562 if (
c_e(this%rect_coo%ilon) .and.
c_e(this%rect_coo%ilat) .and. &
563 c_e(this%rect_coo%flon) .and.
c_e(this%rect_coo%flat))
then 566 if ( this%rect_coo%ilon > this%rect_coo%flon .or. &
567 this%rect_coo%ilat > this%rect_coo%flat )
then 570 "invalid zoom coordinates: ")
572 trim(
to_char(this%rect_coo%ilon))//
'/'// &
573 trim(
to_char(this%rect_coo%flon)))
575 trim(
to_char(this%rect_coo%ilat))//
'/'// &
576 trim(
to_char(this%rect_coo%flat)))
577 call raise_fatal_error()
582 call l4f_category_log(this%category,l4f_error,
"zoom: coord parameters missing")
583 call raise_fatal_error()
587 else if (this%sub_type ==
'coordbb')
then 589 if (
c_e(this%rect_coo%ilon) .and.
c_e(this%rect_coo%ilat) .and. &
590 c_e(this%rect_coo%flon) .and.
c_e(this%rect_coo%flat))
then 594 call raise_fatal_error()
598 else if (this%sub_type ==
'index')
then 600 IF (
c_e(this%rect_ind%ix) .AND.
c_e(this%rect_ind%iy) .AND. &
601 c_e(this%rect_ind%fx) .AND.
c_e(this%rect_ind%fy))
THEN 604 IF (this%rect_ind%ix > this%rect_ind%fx .OR. &
605 this%rect_ind%iy > this%rect_ind%fy)
THEN 609 trim(
to_char(this%rect_ind%ix))//
'/'// &
610 trim(
to_char(this%rect_ind%fx)))
612 trim(
to_char(this%rect_ind%iy))//
'/'// &
613 trim(
to_char(this%rect_ind%fy)))
615 CALL raise_fatal_error()
621 'zoom: index parameters ix, iy, fx, fy not provided')
622 CALL raise_fatal_error()
627 CALL sub_type_error()
631 ELSE IF (this%trans_type ==
'inter' .OR. this%trans_type ==
'intersearch')
THEN 633 IF (this%sub_type ==
'near' .OR. this%sub_type ==
'bilin' .OR. &
634 this%sub_type ==
'linear' .OR. this%sub_type ==
'shapiro_near')
THEN 637 CALL sub_type_error()
641 ELSE IF (this%trans_type ==
'boxregrid' .OR. this%trans_type ==
'boxinter' .OR. &
642 this%trans_type ==
'polyinter' .OR. this%trans_type ==
'maskinter' .OR. &
643 this%trans_type ==
'stencilinter')
THEN 645 IF (this%trans_type ==
'boxregrid')
THEN 646 IF (
c_e(this%box_info%npx) .AND.
c_e(this%box_info%npy))
THEN 647 IF (this%box_info%npx <= 0 .OR. this%box_info%npy <= 0 )
THEN 648 CALL l4f_category_log(this%category,l4f_error,
'boxregrid: invalid parameters '//&
649 trim(
to_char(this%box_info%npx))//
' '//trim(
to_char(this%box_info%npy)))
650 CALL raise_fatal_error()
654 'boxregrid: parameters npx, npy missing')
655 CALL raise_fatal_error()
659 IF (this%trans_type ==
'polyinter')
THEN 660 IF (this%poly%arraysize <= 0)
THEN 662 "polyinter: poly parameter missing or empty")
663 CALL raise_fatal_error()
667 IF (this%trans_type ==
'stencilinter')
THEN 668 IF (.NOT.
c_e(this%area_info%radius))
THEN 670 "stencilinter: radius parameter missing")
671 CALL raise_fatal_error()
675 IF (this%sub_type ==
'average' .OR. this%sub_type ==
'stddev' &
676 .OR. this%sub_type ==
'stddevnm1')
THEN 677 this%stat_info%percentile = rmiss
678 ELSE IF (this%sub_type ==
'max')
THEN 679 this%stat_info%percentile = 101.
680 ELSE IF (this%sub_type ==
'min')
THEN 681 this%stat_info%percentile = -1.
682 ELSE IF (this%sub_type ==
'percentile')
THEN 683 IF (.NOT.
c_e(this%stat_info%percentile))
THEN 685 ':percentile: percentile value not provided')
686 CALL raise_fatal_error()
687 ELSE IF (this%stat_info%percentile >= 100.)
THEN 688 this%sub_type =
'max' 689 ELSE IF (this%stat_info%percentile <= 0.)
THEN 690 this%sub_type =
'min' 692 ELSE IF (this%sub_type ==
'frequency')
THEN 693 IF (.NOT.
c_e(this%interval_info%gt) .AND. .NOT.
c_e(this%interval_info%gt))
THEN 695 ':frequency: lower and/or upper limit not provided')
696 CALL raise_fatal_error()
699 CALL sub_type_error()
703 ELSE IF (this%trans_type ==
'maskgen')
THEN 705 IF (this%sub_type ==
'poly')
THEN 707 IF (this%poly%arraysize <= 0)
THEN 708 CALL l4f_category_log(this%category,l4f_error,
"maskgen:poly poly parameter missing or empty")
709 CALL raise_fatal_error()
712 ELSE IF (this%sub_type ==
'grid')
THEN 716 CALL sub_type_error()
720 ELSE IF (this%trans_type ==
'vertint')
THEN 722 IF (this%vertint%input_levtype == vol7d_level_miss)
THEN 724 'vertint parameter input_levtype not provided')
725 CALL raise_fatal_error()
728 IF (this%vertint%output_levtype == vol7d_level_miss)
THEN 730 'vertint parameter output_levtype not provided')
731 CALL raise_fatal_error()
734 IF (this%sub_type ==
'linear' .OR. this%sub_type ==
'linearsparse')
THEN 737 CALL sub_type_error()
741 ELSE IF (this%trans_type ==
'metamorphosis')
THEN 743 IF (this%sub_type ==
'all')
THEN 745 ELSE IF (this%sub_type ==
'coordbb')
THEN 747 IF (
c_e(this%rect_coo%ilon) .AND.
c_e(this%rect_coo%ilat) .AND. &
748 c_e(this%rect_coo%flon) .AND.
c_e(this%rect_coo%flat))
THEN 751 CALL l4f_category_log(this%category,l4f_error,
"metamorphosis: coordbb parameters missing")
752 CALL raise_fatal_error()
756 ELSE IF (this%sub_type ==
'poly')
THEN 758 IF (this%poly%arraysize <= 0)
THEN 759 CALL l4f_category_log(this%category,l4f_error,
"metamorphosis:poly: poly parameter missing or empty")
760 CALL raise_fatal_error()
763 ELSE IF (this%sub_type ==
'mask' .OR. this%sub_type ==
'maskvalid' .OR. &
764 this%sub_type ==
'maskinvalid' .OR. this%sub_type ==
'setinvalidto' .OR. &
765 this%sub_type ==
'settoinvalid' .OR. this%sub_type ==
'lemaskinvalid' .OR. &
766 this%sub_type ==
'ltmaskinvalid' .OR. this%sub_type ==
'gemaskinvalid' .OR. &
767 this%sub_type ==
'gtmaskinvalid' .OR. this%sub_type ==
'index')
THEN 770 CALL sub_type_error()
775 CALL trans_type_error()
781 SUBROUTINE sub_type_error()
784 //
': sub_type '//trim(this%sub_type)//
' is not defined')
785 CALL raise_fatal_error()
787 END SUBROUTINE sub_type_error
789 SUBROUTINE trans_type_error()
791 CALL l4f_category_log(this%category, l4f_error,
'trans_type '//this%trans_type &
793 CALL raise_fatal_error()
795 END SUBROUTINE trans_type_error
798 END SUBROUTINE transform_init
804 SUBROUTINE transform_delete(this)
805 TYPE(transform_def),
INTENT(inout) :: this
807 this%trans_type=cmiss
810 this%rect_ind%ix=imiss
811 this%rect_ind%iy=imiss
812 this%rect_ind%fx=imiss
813 this%rect_ind%fy=imiss
815 this%rect_coo%ilon=dmiss
816 this%rect_coo%ilat=dmiss
817 this%rect_coo%flon=dmiss
818 this%rect_coo%flat=dmiss
820 this%box_info%npx=imiss
821 this%box_info%npy=imiss
826 CALL l4f_category_delete(this%category)
828 END SUBROUTINE transform_delete
832 SUBROUTINE transform_get_val(this, time_definition, trans_type, sub_type, &
833 input_levtype, output_levtype)
834 type(transform_def),
intent(in) :: this
835 INTEGER,
INTENT(out),
OPTIONAL :: time_definition
836 CHARACTER(len=*),
INTENT(out),
OPTIONAL :: trans_type
837 CHARACTER(len=*),
INTENT(out),
OPTIONAL :: sub_type
838 TYPE(vol7d_level),
INTENT(out),
OPTIONAL :: input_levtype
840 TYPE(vol7d_level),
INTENT(out),
OPTIONAL :: output_levtype
843 IF (
PRESENT(time_definition)) time_definition=this%time_definition
844 IF (
PRESENT(trans_type)) trans_type = this%trans_type
845 IF (
PRESENT(sub_type)) sub_type = this%sub_type
846 IF (
PRESENT(input_levtype)) input_levtype = this%vertint%input_levtype
847 IF (
PRESENT(output_levtype)) output_levtype = this%vertint%output_levtype
850 END SUBROUTINE transform_get_val
896 SUBROUTINE grid_transform_levtype_levtype_init(this, trans, lev_in, lev_out, &
897 coord_3d_in, categoryappend)
898 TYPE(grid_transform),
INTENT(out) :: this
899 TYPE(transform_def),
INTENT(in) :: trans
900 TYPE(vol7d_level),
INTENT(in) :: lev_in(:)
901 TYPE(vol7d_level),
INTENT(in) :: lev_out(:)
902 REAL,
INTENT(inout),
OPTIONAL,
ALLOCATABLE :: coord_3d_in(:,:,:)
903 CHARACTER(len=*),
INTENT(in),
OPTIONAL :: categoryappend
905 DOUBLE PRECISION :: coord_in(SIZE(lev_in))
906 DOUBLE PRECISION,
ALLOCATABLE :: coord_out(:)
907 LOGICAL :: mask_in(SIZE(lev_in))
908 LOGICAL,
ALLOCATABLE :: mask_out(:)
910 INTEGER :: i, j, icache, inused, istart, iend, ostart, oend
913 CALL grid_transform_init_common(this, trans, categoryappend)
918 IF (this%trans%trans_type ==
'vertint')
THEN 920 IF (
c_e(trans%vertint%input_levtype%level2) .AND. &
921 trans%vertint%input_levtype%level1 /= trans%vertint%input_levtype%level2)
THEN 923 'vertint: input upper and lower surface must be of the same type, '// &
924 t2c(trans%vertint%input_levtype%level1)//
'/='// &
925 t2c(trans%vertint%input_levtype%level2))
929 IF (
c_e(trans%vertint%output_levtype%level2) .AND. &
930 trans%vertint%output_levtype%level1 /= trans%vertint%output_levtype%level2)
THEN 932 'vertint: output upper and lower surface must be of the same type'// &
933 t2c(trans%vertint%output_levtype%level1)//
'/='// &
934 t2c(trans%vertint%output_levtype%level2))
939 mask_in(:) = (lev_in(:)%level1 == trans%vertint%input_levtype%level1) .AND. &
940 (lev_in(:)%level2 == trans%vertint%input_levtype%level2)
941 CALL make_vert_coord(lev_in, mask_in, coord_in, dolog)
942 this%innz =
SIZE(lev_in)
943 istart = firsttrue(mask_in)
944 iend = lasttrue(mask_in)
945 inused = iend - istart + 1
946 IF (inused /= count(mask_in))
THEN 948 'grid_transform_levtype_levtype_init: input levels badly sorted '//&
949 t2c(inused)//
'/'//t2c(count(mask_in)))
953 this%levshift = istart-1
954 this%levused = inused
956 IF (trans%vertint%input_levtype%level1 /= trans%vertint%output_levtype%level1)
THEN 959 'vertint: different input and output level types '// &
960 t2c(trans%vertint%input_levtype%level1)//
' '// &
961 t2c(trans%vertint%output_levtype%level1))
964 ALLOCATE(mask_out(
SIZE(lev_out)), this%vcoord_out(
SIZE(lev_out)))
965 mask_out(:) = (lev_out(:)%level1 == trans%vertint%output_levtype%level1) .AND. &
966 (lev_out(:)%level2 == trans%vertint%output_levtype%level2)
967 CALL make_vert_coord(lev_out, mask_out, this%vcoord_out, dolog)
968 this%outnz =
SIZE(mask_out)
971 IF (.NOT.
PRESENT(coord_3d_in))
THEN 973 'vertint: different input and output level types & 974 &and no coord_3d_in, expecting vert. coord. in volume')
977 IF (
SIZE(coord_3d_in,3) /= inused)
THEN 979 'vertint: vertical size of coord_3d_in (vertical coordinate) & 980 &different from number of input levels suitable for interpolation')
982 'coord_3d_in: '//t2c(
SIZE(coord_3d_in,3))// &
983 ', input levels for interpolation: '//t2c(inused))
988 CALL move_alloc(coord_3d_in, this%coord_3d_in)
990 WHERE(
c_e(this%coord_3d_in) .AND. this%coord_3d_in > 0.0)
991 this%coord_3d_in = log(this%coord_3d_in)
993 this%coord_3d_in = rmiss
1005 'vertint: equal input and output level types '// &
1006 t2c(trans%vertint%input_levtype%level1))
1009 IF (
SIZE(lev_out) > 0)
THEN 1010 ALLOCATE(mask_out(
SIZE(lev_out)), coord_out(
SIZE(lev_out)))
1011 mask_out(:) = (lev_out(:)%level1 == trans%vertint%output_levtype%level1) .AND. &
1012 (lev_out(:)%level2 == trans%vertint%output_levtype%level2)
1013 CALL make_vert_coord(lev_out, mask_out, coord_out, dolog)
1016 IF (
c_e(trans%vertint%input_levtype%level2) .AND. &
1017 .NOT.
c_e(trans%vertint%output_levtype%level2))
THEN 1018 IF (trans%vertint%output_levtype%level1 == 105 .OR. &
1019 trans%vertint%output_levtype%level1 == 150)
THEN 1020 ALLOCATE(this%output_level_auto(inused-1))
1022 'grid_transform_levtype_levtype_init: autogenerating '//t2c(inused-1) &
1023 //
'/'//t2c(iend-istart)//
' output levels (f->h)')
1024 DO i = istart, iend - 1
1025 CALL init(this%output_level_auto(i-istart+1), &
1026 trans%vertint%input_levtype%level1, lev_in(i)%l2)
1030 'grid_transform_levtype_levtype_init: automatic generation of output levels & 1031 &available only for hybrid levels')
1035 ELSE IF (.NOT.
c_e(trans%vertint%input_levtype%level2) .AND. &
1036 c_e(trans%vertint%output_levtype%level2))
THEN 1037 ALLOCATE(this%output_level_auto(inused-1))
1038 IF (trans%vertint%output_levtype%level1 == 105 .OR. &
1039 trans%vertint%output_levtype%level1 == 150)
THEN 1041 'grid_transform_levtype_levtype_init: autogenerating '//t2c(inused-1) &
1042 //
'/'//t2c(iend-istart)//
' output levels (h->f)')
1043 DO i = istart, iend - 1
1044 CALL init(this%output_level_auto(i-istart+1), trans%vertint%input_levtype%level1, &
1045 lev_in(i)%l1, trans%vertint%input_levtype%level1, &
1050 'grid_transform_levtype_levtype_init: automatic generation of output levels & 1051 &available only for hybrid levels')
1057 'grid_transform_levtype_levtype_init: strange situation'// &
1058 to_char(
c_e(trans%vertint%input_levtype%level2))//
' '// &
1059 to_char(
c_e(trans%vertint%output_levtype%level2)))
1063 ALLOCATE(coord_out(inused-1), mask_out(inused-1))
1064 mask_out(:) = .true.
1065 CALL make_vert_coord(this%output_level_auto, mask_out, coord_out, dolog)
1068 this%outnz =
SIZE(mask_out)
1069 ostart = firsttrue(mask_out)
1070 oend = lasttrue(mask_out)
1073 IF (istart == 0)
THEN 1075 'grid_transform_levtype_levtype_init: & 1076 &input contains no vertical levels of type ('// &
1077 trim(
to_char(trans%vertint%input_levtype%level1))//
','// &
1078 trim(
to_char(trans%vertint%input_levtype%level2))// &
1079 ') suitable for interpolation')
1082 ELSE IF (istart == iend)
THEN 1084 'grid_transform_levtype_levtype_init: & 1085 &input contains only 1 vertical level of type ('// &
1086 trim(
to_char(trans%vertint%input_levtype%level1))//
','// &
1087 trim(
to_char(trans%vertint%input_levtype%level2))// &
1088 ') suitable for interpolation')
1090 IF (ostart == 0)
THEN 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')
1102 IF (this%trans%sub_type ==
'linear')
THEN 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 1110 this%inter_index_z(:) = istart
1111 this%inter_zp(:) = 1.0d0
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))
1129 IF (this%trans%extrap .AND. iend > 1)
THEN 1130 this%inter_index_z(j) = iend - 1
1131 this%inter_zp(j) = 0.0d0
1135 DEALLOCATE(coord_out, mask_out)
1138 ELSE IF (this%trans%sub_type ==
'linearsparse')
THEN 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)
1154 END SUBROUTINE grid_transform_levtype_levtype_init
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
1166 DOUBLE PRECISION :: fact
1173 IF (any(lev(k)%level1 == height_level))
THEN 1175 ELSE IF (any(lev(k)%level1 == thermo_level))
THEN 1177 ELSE IF (any(lev(k)%level1 == sigma_level))
THEN 1183 IF (
c_e(lev(k)%level2) .AND. lev(k)%level1 == lev(k)%level2)
THEN 1184 IF (lev(k)%level1 == 100 .OR. lev(k)%level1 == 108)
THEN 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
1191 coord(:) = (lev(:)%l1 + lev(:)%l2)*fact*0.5d0
1195 IF (lev(k)%level1 == 100 .OR. lev(k)%level1 == 108)
THEN 1196 WHERE(mask(:) .AND. lev(:)%l1 > 0)
1197 coord(:) = log(dble(lev(:)%l1)*fact)
1202 coord(:) = lev(:)%l1*fact
1208 mask(:) = mask(:) .AND.
c_e(coord(:))
1210 END SUBROUTINE make_vert_coord
1230 SUBROUTINE grid_transform_init(this, trans, in, out, maskgrid, maskbounds, &
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
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
1250 CALL grid_transform_init_common(this, trans, categoryappend)
1252 CALL l4f_category_log(this%category, l4f_debug,
"grid_transform vg6d-vg6d")
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)
1259 IF (this%trans%trans_type ==
'zoom')
THEN 1261 IF (this%trans%sub_type ==
'coord')
THEN 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)
1269 ELSE IF (this%trans%sub_type ==
'projcoord')
THEN 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)
1277 ELSE IF (this%trans%sub_type ==
'coordbb')
THEN 1282 CALL get_val(lin, nx=nx, ny=ny)
1284 ALLOCATE(point_mask(nx,ny))
1285 point_mask(:,:) = .false.
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 1295 point_mask(i,j) = .true.
1302 IF (any(point_mask(i,:)))
EXIT 1304 this%trans%rect_ind%ix = i
1305 DO i = nx, this%trans%rect_ind%ix, -1
1306 IF (any(point_mask(i,:)))
EXIT 1308 this%trans%rect_ind%fx = i
1311 IF (any(point_mask(:,j)))
EXIT 1313 this%trans%rect_ind%iy = j
1314 DO j = ny, this%trans%rect_ind%iy, -1
1315 IF (any(point_mask(:,j)))
EXIT 1317 this%trans%rect_ind%fy = j
1319 DEALLOCATE(point_mask)
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 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)))
1338 CALL get_val(in, nx=nx, ny=ny, xmin=xmin, xmax=xmax, &
1339 ymin=ymin, ymax=ymax, dx=steplon, dy=steplat)
1342 this%iniox = min(max(this%trans%rect_ind%ix,1),nx)
1343 this%inioy = min(max(this%trans%rect_ind%iy,1),ny)
1344 this%infox = max(min(this%trans%rect_ind%fx,nx),1)
1345 this%infoy = max(min(this%trans%rect_ind%fy,ny),1)
1347 this%outinx = min(max(2-this%trans%rect_ind%ix,1),nx)
1348 this%outiny = min(max(2-this%trans%rect_ind%iy,1),ny)
1349 this%outfnx = min(this%trans%rect_ind%fx,nx)-this%trans%rect_ind%ix+1
1350 this%outfny = min(this%trans%rect_ind%fy,ny)-this%trans%rect_ind%iy+1
1352 xmin=xmin+steplon*(this%trans%rect_ind%ix-1)
1353 ymin=ymin+steplat*(this%trans%rect_ind%iy-1)
1354 xmax=xmax+steplon*(this%trans%rect_ind%fx-nx)
1355 ymax=ymax+steplat*(this%trans%rect_ind%fy-ny)
1359 CALL dealloc(out%dim)
1361 out%dim%nx = this%trans%rect_ind%fx - this%trans%rect_ind%ix + 1
1362 out%dim%ny = this%trans%rect_ind%fy - this%trans%rect_ind%iy + 1
1363 this%outnx = out%dim%nx
1364 this%outny = out%dim%ny
1368 CALL set_val(out, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
1372 ELSE IF (this%trans%trans_type ==
'boxregrid')
THEN 1374 CALL get_val(in, nx=nx, ny=ny, xmin=xmin, xmax=xmax, &
1375 ymin=ymin, ymax=ymax, dx=steplon, dy=steplat)
1381 xmin_new = xmin + (this%trans%box_info%npx - 1)*0.5d0*steplon
1382 ymin_new = ymin + (this%trans%box_info%npy - 1)*0.5d0*steplat
1386 CALL dealloc(out%dim)
1388 out%dim%nx = nx/this%trans%box_info%npx
1389 out%dim%ny = ny/this%trans%box_info%npy
1390 this%outnx = out%dim%nx
1391 this%outny = out%dim%ny
1392 steplon = steplon*this%trans%box_info%npx
1393 steplat = steplat*this%trans%box_info%npy
1395 CALL set_val(out, xmin=xmin_new, ymin=ymin_new, &
1396 xmax=xmin_new + dble(out%dim%nx-1)*steplon, dx=steplon, &
1397 ymax=ymin_new + dble(out%dim%ny-1)*steplat, dy=steplat)
1401 ELSE IF (this%trans%trans_type ==
'inter' .OR. this%trans%trans_type ==
'intersearch')
THEN 1403 CALL outgrid_setup()
1405 IF (this%trans%sub_type ==
'near' .OR. this%trans%sub_type ==
'bilin'&
1406 .OR. this%trans%sub_type ==
'shapiro_near')
THEN 1408 CALL get_val(in, nx=this%innx, ny=this%inny, &
1409 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
1410 CALL get_val(out, nx=this%outnx, ny=this%outny)
1412 ALLOCATE(this%inter_index_x(this%outnx,this%outny), &
1413 this%inter_index_y(this%outnx,this%outny))
1414 CALL copy(out, lout)
1417 IF (this%trans%sub_type ==
'bilin')
THEN 1418 CALL this%find_index(in, .false., &
1419 this%innx, this%inny, xmin, xmax, ymin, ymax, &
1420 lout%dim%lon, lout%dim%lat, this%trans%extrap, &
1421 this%inter_index_x, this%inter_index_y)
1423 ALLOCATE(this%inter_x(this%innx,this%inny), &
1424 this%inter_y(this%innx,this%inny))
1425 ALLOCATE(this%inter_xp(this%outnx,this%outny), &
1426 this%inter_yp(this%outnx,this%outny))
1429 CALL griddim_gen_coord(in, this%inter_x, this%inter_y)
1431 CALL proj(in, lout%dim%lon, lout%dim%lat, this%inter_xp, this%inter_yp)
1434 CALL this%find_index(in, .true., &
1435 this%innx, this%inny, xmin, xmax, ymin, ymax, &
1436 lout%dim%lon, lout%dim%lat, this%trans%extrap, &
1437 this%inter_index_x, this%inter_index_y)
1439 IF (this%trans%trans_type ==
'intersearch')
THEN 1440 ALLOCATE(this%inter_x(this%innx,this%inny), &
1441 this%inter_y(this%innx,this%inny))
1442 ALLOCATE(this%inter_xp(this%outnx,this%outny), &
1443 this%inter_yp(this%outnx,this%outny))
1446 CALL griddim_gen_coord(in, this%inter_x, this%inter_y)
1448 CALL proj(in, lout%dim%lon, lout%dim%lat, this%inter_xp, this%inter_yp)
1456 ELSE IF (this%trans%trans_type ==
'boxinter')
THEN 1458 CALL outgrid_setup()
1459 CALL get_val(in, nx=this%innx, ny=this%inny)
1460 CALL get_val(out, nx=this%outnx, ny=this%outny, &
1461 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
1464 IF (.NOT.
c_e(this%trans%area_info%boxdx)) &
1465 CALL get_val(out, dx=this%trans%area_info%boxdx)
1466 IF (.NOT.
c_e(this%trans%area_info%boxdy)) &
1467 CALL get_val(out, dx=this%trans%area_info%boxdy)
1469 this%trans%area_info%boxdx = this%trans%area_info%boxdx*0.5d0
1470 this%trans%area_info%boxdy = this%trans%area_info%boxdy*0.5d0
1472 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
1473 this%inter_index_y(this%innx,this%inny))
1479 CALL this%find_index(out, .true., &
1480 this%outnx, this%outny, xmin, xmax, ymin, ymax, &
1481 lin%dim%lon, lin%dim%lat, .false., &
1482 this%inter_index_x, this%inter_index_y)
1487 ELSE IF (this%trans%trans_type ==
'stencilinter')
THEN 1489 CALL outgrid_setup()
1491 CALL get_val(in, nx=this%innx, ny=this%inny, &
1492 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
1493 CALL get_val(out, nx=this%outnx, ny=this%outny)
1495 ALLOCATE (this%inter_index_x(this%outnx,this%outny), &
1496 this%inter_index_y(this%outnx,this%outny))
1497 CALL copy(out, lout)
1499 CALL this%find_index(in, .true., &
1500 this%innx, this%inny, xmin, xmax, ymin, ymax, &
1501 lout%dim%lon, lout%dim%lat, this%trans%extrap, &
1502 this%inter_index_x, this%inter_index_y)
1505 nr = int(this%trans%area_info%radius)
1508 r2 = this%trans%area_info%radius**2
1509 ALLOCATE(this%stencil(n,n))
1510 this%stencil(:,:) = .true.
1513 IF ((ix-nm)**2+(iy-nm)**2 > r2) this%stencil(ix,iy) = .false.
1520 xnmax = this%innx - nr
1522 ynmax = this%inny - nr
1523 DO iy = 1, this%outny
1524 DO ix = 1, this%outnx
1525 IF (this%inter_index_x(ix,iy) < xnmin .OR. &
1526 this%inter_index_x(ix,iy) > xnmax .OR. &
1527 this%inter_index_y(ix,iy) < ynmin .OR. &
1528 this%inter_index_y(ix,iy) > ynmax)
THEN 1529 this%inter_index_x(ix,iy) = imiss
1530 this%inter_index_y(ix,iy) = imiss
1537 'stencilinter: stencil size '//t2c(n*n))
1539 'stencilinter: stencil points '//t2c(count(this%stencil)))
1545 ELSE IF (this%trans%trans_type ==
'maskgen')
THEN 1547 IF (this%trans%sub_type ==
'poly')
THEN 1550 CALL get_val(in, nx=this%innx, ny=this%inny)
1551 this%outnx = this%innx
1552 this%outny = this%inny
1555 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
1556 this%inter_index_y(this%innx,this%inny))
1557 this%inter_index_x(:,:) = imiss
1558 this%inter_index_y(:,:) = 1
1567 inside_x:
DO i = 1, this%innx
1568 point = georef_coord_new(x=out%dim%lon(i,j), y=out%dim%lat(i,j))
1570 DO n = nprev, this%trans%poly%arraysize
1571 IF (
inside(point, this%trans%poly%array(n)))
THEN 1572 this%inter_index_x(i,j) = n
1577 DO n = nprev-1, 1, -1
1578 IF (
inside(point, this%trans%poly%array(n)))
THEN 1579 this%inter_index_x(i,j) = n
1590 ELSE IF (this%trans%sub_type ==
'grid')
THEN 1593 CALL copy(out, lout)
1596 CALL get_val(in, nx=this%innx, ny=this%inny)
1597 this%outnx = this%innx
1598 this%outny = this%inny
1599 CALL get_val(lout, nx=nx, ny=ny, &
1600 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
1603 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
1604 this%inter_index_y(this%innx,this%inny))
1610 CALL this%find_index(lout, .true., &
1611 nx, ny, xmin, xmax, ymin, ymax, &
1612 out%dim%lon, out%dim%lat, .false., &
1613 this%inter_index_x, this%inter_index_y)
1615 WHERE(
c_e(this%inter_index_x(:,:)))
1616 this%inter_index_x(:,:) = this%inter_index_x(:,:) + &
1617 (this%inter_index_y(:,:)-1)*nx
1625 ELSE IF (this%trans%trans_type ==
'polyinter')
THEN 1631 CALL get_val(in, nx=this%innx, ny=this%inny)
1632 this%outnx = this%innx
1633 this%outny = this%inny
1636 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
1637 this%inter_index_y(this%innx,this%inny))
1638 this%inter_index_x(:,:) = imiss
1639 this%inter_index_y(:,:) = 1
1648 inside_x_2:
DO i = 1, this%innx
1649 point = georef_coord_new(x=out%dim%lon(i,j), y=out%dim%lat(i,j))
1651 DO n = nprev, this%trans%poly%arraysize
1652 IF (
inside(point, this%trans%poly%array(n)))
THEN 1653 this%inter_index_x(i,j) = n
1658 DO n = nprev-1, 1, -1
1659 IF (
inside(point, this%trans%poly%array(n)))
THEN 1660 this%inter_index_x(i,j) = n
1673 ELSE IF (this%trans%trans_type ==
'metamorphosis')
THEN 1676 CALL get_val(in, nx=this%innx, ny=this%inny)
1677 this%outnx = this%innx
1678 this%outny = this%inny
1680 IF (this%trans%sub_type ==
'maskvalid' .OR. this%trans%sub_type ==
'maskinvalid')
THEN 1682 IF (.NOT.
PRESENT(maskgrid))
THEN 1684 'grid_transform_init maskgrid argument missing for metamorphosis:'// &
1685 trim(this%trans%sub_type)//
' transformation')
1690 IF (this%innx /=
SIZE(maskgrid,1) .OR. this%inny /=
SIZE(maskgrid,2))
THEN 1692 'grid_transform_init mask non conformal with input field')
1694 'mask: '//t2c(
SIZE(maskgrid,1))//
'x'//t2c(
SIZE(maskgrid,2))// &
1695 ' input field:'//t2c(this%innx)//
'x'//t2c(this%inny))
1700 ALLOCATE(this%point_mask(this%innx,this%inny))
1702 IF (this%trans%sub_type ==
'maskvalid')
THEN 1705 IF (.NOT.
PRESENT(maskbounds))
THEN 1706 this%point_mask(:,:) =
c_e(maskgrid(:,:))
1707 ELSE IF (
SIZE(maskbounds) < 2)
THEN 1708 this%point_mask(:,:) =
c_e(maskgrid(:,:))
1710 this%point_mask(:,:) =
c_e(maskgrid(:,:)) .AND. &
1711 maskgrid(:,:) > maskbounds(1) .AND. &
1712 maskgrid(:,:) <= maskbounds(
SIZE(maskbounds))
1715 this%point_mask(:,:) = .NOT.
c_e(maskgrid(:,:))
1720 ELSE IF (this%trans%sub_type ==
'lemaskinvalid' .OR. &
1721 this%trans%sub_type ==
'ltmaskinvalid' .OR. &
1722 this%trans%sub_type ==
'gemaskinvalid' .OR. &
1723 this%trans%sub_type ==
'gtmaskinvalid')
THEN 1726 this%val_mask = maskgrid
1729 ELSE IF (this%trans%sub_type ==
'setinvalidto')
THEN 1731 IF (.NOT.
PRESENT(maskbounds))
THEN 1733 'grid_transform_init maskbounds missing for metamorphosis:'// &
1734 trim(this%trans%sub_type)//
' transformation')
1736 ELSE IF (
SIZE(maskbounds) < 1)
THEN 1738 'grid_transform_init maskbounds empty for metamorphosis:'// &
1739 trim(this%trans%sub_type)//
' transformation')
1742 this%val1 = maskbounds(1)
1745 "grid_transform_init setting invalid data to "//t2c(this%val1))
1751 ELSE IF (this%trans%sub_type ==
'settoinvalid')
THEN 1753 IF (.NOT.
PRESENT(maskbounds))
THEN 1755 'grid_transform_init maskbounds missing for metamorphosis:'// &
1756 trim(this%trans%sub_type)//
' transformation')
1759 ELSE IF (
SIZE(maskbounds) < 2)
THEN 1761 'grid_transform_init maskbounds must have at least 2 elements for metamorphosis:'// &
1762 trim(this%trans%sub_type)//
' transformation')
1766 this%val1 = maskbounds(1)
1767 this%val2 = maskbounds(
SIZE(maskbounds))
1770 "grid_transform_init setting to invalid interval ]"//t2c(this%val1)//
','// &
1771 t2c(this%val2)//
']')
1785 SUBROUTINE outgrid_setup()
1788 CALL griddim_setsteps(out)
1790 CALL get_val(in,
proj=proj_in, component_flag=cf_i)
1791 CALL get_val(out,
proj=proj_out, component_flag=cf_o)
1792 IF (proj_in == proj_out)
THEN 1795 CALL set_val(out, component_flag=cf_i)
1801 'trying to interpolate a grid with component flag 1 to a grid on a different projection')
1803 'vector fields will probably be wrong')
1805 CALL set_val(out, component_flag=cf_i)
1809 CALL griddim_set_central_lon(in, griddim_central_lon(out))
1811 END SUBROUTINE outgrid_setup
1813 END SUBROUTINE grid_transform_init
1858 SUBROUTINE grid_transform_grid_vol7d_init(this, trans, in, v7d_out, &
1859 maskgrid, maskbounds, find_index, categoryappend)
1860 TYPE(grid_transform),
INTENT(out) :: this
1861 TYPE(transform_def),
INTENT(in) :: trans
1862 TYPE(griddim_def),
INTENT(in) :: in
1863 TYPE(vol7d),
INTENT(inout) :: v7d_out
1864 REAL,
INTENT(in),
OPTIONAL :: maskgrid(:,:)
1865 REAL,
INTENT(in),
OPTIONAL :: maskbounds(:)
1866 PROCEDURE(basic_find_index),
POINTER,
OPTIONAL :: find_index
1867 CHARACTER(len=*),
INTENT(in),
OPTIONAL :: categoryappend
1869 INTEGER :: ix, iy, n, nm, nr, nprev, nmaskarea, xnmin, xnmax, ynmin, ynmax, &
1871 DOUBLE PRECISION :: xmin, xmax, ymin, ymax, r2, lonref
1872 DOUBLE PRECISION,
ALLOCATABLE :: lon1(:), lat1(:), lon(:,:), lat(:,:)
1873 REAL,
ALLOCATABLE :: lmaskbounds(:)
1874 TYPE(georef_coord) :: point
1875 TYPE(griddim_def) :: lin
1878 IF (
PRESENT(find_index))
THEN 1879 IF (
ASSOCIATED(find_index))
THEN 1880 this%find_index => find_index
1883 CALL grid_transform_init_common(this, trans, categoryappend)
1889 CALL get_val(trans, time_definition=time_definition)
1890 IF (.NOT.
c_e(time_definition))
THEN 1894 IF (this%trans%trans_type ==
'inter')
THEN 1896 IF (this%trans%sub_type ==
'near' .OR. this%trans%sub_type ==
'bilin' &
1897 .OR. this%trans%sub_type ==
'shapiro_near')
THEN 1900 CALL get_val(lin, nx=this%innx, ny=this%inny)
1901 this%outnx =
SIZE(v7d_out%ana)
1904 ALLOCATE (this%inter_index_x(this%outnx,this%outny),&
1905 this%inter_index_y(this%outnx,this%outny))
1906 ALLOCATE(lon(this%outnx,1),lat(this%outnx,1))
1908 CALL getval(v7d_out%ana(:)%coord,lon=lon(:,1),lat=lat(:,1))
1910 lonref = 0.5d0*(maxval(lon(:,1), mask=
c_e(lon(:,1))) + minval(lon(:,1), mask=
c_e(lon(:,1))))
1911 CALL griddim_set_central_lon(lin, lonref)
1912 CALL get_val(lin, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
1914 IF (this%trans%sub_type ==
'bilin')
THEN 1915 CALL this%find_index(lin, .false., &
1916 this%innx, this%inny, xmin, xmax, ymin, ymax, &
1917 lon, lat, this%trans%extrap, &
1918 this%inter_index_x, this%inter_index_y)
1920 ALLOCATE(this%inter_x(this%innx,this%inny),this%inter_y(this%innx,this%inny))
1921 ALLOCATE(this%inter_xp(this%outnx,this%outny),this%inter_yp(this%outnx,this%outny))
1923 CALL griddim_gen_coord(lin, this%inter_x, this%inter_y)
1924 CALL proj(lin, lon, lat, this%inter_xp, this%inter_yp)
1927 CALL this%find_index(lin, .true., &
1928 this%innx, this%inny, xmin, xmax, ymin, ymax, &
1929 lon, lat, this%trans%extrap, &
1930 this%inter_index_x, this%inter_index_y)
1932 IF (this%trans%trans_type ==
'intersearch')
THEN 1933 ALLOCATE(this%inter_x(this%innx,this%inny),this%inter_y(this%innx,this%inny))
1934 ALLOCATE(this%inter_xp(this%outnx,this%outny),this%inter_yp(this%outnx,this%outny))
1936 CALL griddim_gen_coord(lin, this%inter_x, this%inter_y)
1937 CALL proj(lin, lon, lat, this%inter_xp, this%inter_yp)
1948 ELSE IF (this%trans%trans_type ==
'polyinter')
THEN 1950 CALL get_val(in, nx=this%innx, ny=this%inny)
1952 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
1953 this%inter_index_y(this%innx,this%inny))
1954 this%inter_index_x(:,:) = imiss
1955 this%inter_index_y(:,:) = 1
1961 this%outnx = this%trans%poly%arraysize
1964 CALL init(v7d_out, time_definition=time_definition)
1965 CALL vol7d_alloc(v7d_out, nana=this%outnx)
1968 ALLOCATE(lon(this%outnx,1))
1969 CALL getval(v7d_out%ana(:)%coord,lon=lon(:,1))
1970 lonref = 0.5d0*(maxval(lon(:,1), mask=
c_e(lon(:,1))) + minval(lon(:,1), mask=
c_e(lon(:,1))))
1971 CALL griddim_set_central_lon(lin, lonref)
1976 CALL poly_to_coordinates(this%trans%poly, v7d_out)
1981 DO iy = 1, this%inny
1982 inside_x:
DO ix = 1, this%innx
1983 point = georef_coord_new(x=lin%dim%lon(ix,iy), y=lin%dim%lat(ix,iy))
1985 DO n = nprev, this%trans%poly%arraysize
1986 IF (
inside(point, this%trans%poly%array(n)))
THEN 1987 this%inter_index_x(ix,iy) = n
1992 DO n = nprev-1, 1, -1
1993 IF (
inside(point, this%trans%poly%array(n)))
THEN 1994 this%inter_index_x(ix,iy) = n
2006 DO n = 1, this%trans%poly%arraysize
2008 'Polygon: '//t2c(n)//
' grid points: '// &
2009 t2c(count(this%inter_index_x(:,:) == n)))
2016 ELSE IF (this%trans%trans_type ==
'stencilinter')
THEN 2020 CALL get_val(lin, nx=this%innx, ny=this%inny)
2021 this%outnx =
SIZE(v7d_out%ana)
2024 ALLOCATE (this%inter_index_x(this%outnx,this%outny),&
2025 this%inter_index_y(this%outnx,this%outny))
2026 ALLOCATE(lon(this%outnx,1),lat(this%outnx,1))
2028 CALL getval(v7d_out%ana(:)%coord,lon=lon(:,1),lat=lat(:,1))
2030 lonref = 0.5d0*(maxval(lon(:,1), mask=
c_e(lon(:,1))) + minval(lon(:,1), mask=
c_e(lon(:,1))))
2031 CALL griddim_set_central_lon(lin, lonref)
2033 CALL get_val(lin, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
2035 CALL this%find_index(lin, .true., &
2036 this%innx, this%inny, xmin, xmax, ymin, ymax, &
2037 lon, lat, this%trans%extrap, &
2038 this%inter_index_x, this%inter_index_y)
2041 nr = int(this%trans%area_info%radius)
2044 r2 = this%trans%area_info%radius**2
2045 ALLOCATE(this%stencil(n,n))
2046 this%stencil(:,:) = .true.
2049 IF ((ix-nm)**2+(iy-nm)**2 > r2) this%stencil(ix,iy) = .false.
2056 xnmax = this%innx - nr
2058 ynmax = this%inny - nr
2059 DO iy = 1, this%outny
2060 DO ix = 1, this%outnx
2061 IF (this%inter_index_x(ix,iy) < xnmin .OR. &
2062 this%inter_index_x(ix,iy) > xnmax .OR. &
2063 this%inter_index_y(ix,iy) < ynmin .OR. &
2064 this%inter_index_y(ix,iy) > ynmax)
THEN 2065 this%inter_index_x(ix,iy) = imiss
2066 this%inter_index_y(ix,iy) = imiss
2073 'stencilinter: stencil size '//t2c(n*n))
2075 'stencilinter: stencil points '//t2c(count(this%stencil)))
2083 ELSE IF (this%trans%trans_type ==
'maskinter')
THEN 2085 IF (.NOT.
PRESENT(maskgrid))
THEN 2087 'grid_transform_init maskgrid argument missing for maskinter transformation')
2088 CALL raise_fatal_error()
2091 CALL get_val(in, nx=this%innx, ny=this%inny)
2092 IF (this%innx /=
SIZE(maskgrid,1) .OR. this%inny /=
SIZE(maskgrid,2))
THEN 2094 'grid_transform_init mask non conformal with input field')
2096 'mask: '//t2c(
SIZE(maskgrid,1))//
'x'//t2c(
SIZE(maskgrid,2))// &
2097 ' input field:'//t2c(this%innx)//
'x'//t2c(this%inny))
2098 CALL raise_fatal_error()
2101 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
2102 this%inter_index_y(this%innx,this%inny))
2103 this%inter_index_x(:,:) = imiss
2104 this%inter_index_y(:,:) = 1
2107 CALL gen_mask_class()
2115 DO iy = 1, this%inny
2116 DO ix = 1, this%innx
2117 IF (
c_e(maskgrid(ix,iy)))
THEN 2118 IF (maskgrid(ix,iy) <= lmaskbounds(nmaskarea+1))
THEN 2119 DO n = nmaskarea, 1, -1
2120 IF (maskgrid(ix,iy) > lmaskbounds(n))
THEN 2121 this%inter_index_x(ix,iy) = n
2131 this%outnx = nmaskarea
2134 CALL init(v7d_out, time_definition=time_definition)
2135 CALL vol7d_alloc(v7d_out, nana=nmaskarea)
2140 CALL init(v7d_out%ana(n), &
2142 mask=(this%inter_index_x(:,:) == n))), &
2144 mask=(this%inter_index_x(:,:) == n))))
2150 ELSE IF (this%trans%trans_type ==
'metamorphosis')
THEN 2157 CALL get_val(in, nx=this%innx, ny=this%inny)
2159 ALLOCATE(this%point_index(this%innx,this%inny))
2160 this%point_index(:,:) = imiss
2162 IF (this%trans%sub_type /=
'index')
THEN 2164 CALL init(v7d_out, time_definition=time_definition)
2167 IF (this%trans%sub_type ==
'all' )
THEN 2169 this%outnx = this%innx*this%inny
2171 CALL vol7d_alloc(v7d_out, nana=this%outnx)
2176 CALL init(v7d_out%ana((iy-1)*this%innx+ix), &
2177 lon=lin%dim%lon(ix,iy),lat=lin%dim%lat(ix,iy))
2179 this%point_index(ix,iy) = n
2185 ELSE IF (this%trans%sub_type ==
'coordbb' )
THEN 2190 DO iy = 1, this%inny
2191 DO ix = 1, this%innx
2193 IF (lin%dim%lon(ix,iy) > this%trans%rect_coo%ilon .AND. &
2194 lin%dim%lon(ix,iy) < this%trans%rect_coo%flon .AND. &
2195 lin%dim%lat(ix,iy) > this%trans%rect_coo%ilat .AND. &
2196 lin%dim%lat(ix,iy) < this%trans%rect_coo%flat)
THEN 2197 this%outnx = this%outnx + 1
2198 this%point_index(ix,iy) = this%outnx
2203 IF (this%outnx <= 0)
THEN 2205 "metamorphosis:coordbb: no points inside bounding box "//&
2206 trim(
to_char(this%trans%rect_coo%ilon))//
","// &
2207 trim(
to_char(this%trans%rect_coo%flon))//
","// &
2208 trim(
to_char(this%trans%rect_coo%ilat))//
","// &
2209 trim(
to_char(this%trans%rect_coo%flat)))
2212 CALL vol7d_alloc(v7d_out, nana=this%outnx)
2216 DO iy = 1, this%inny
2217 DO ix = 1, this%innx
2218 IF (
c_e(this%point_index(ix,iy)))
THEN 2220 CALL init(v7d_out%ana(n), &
2221 lon=lin%dim%lon(ix,iy), lat=lin%dim%lat(ix,iy))
2228 ELSE IF (this%trans%sub_type ==
'poly' )
THEN 2241 DO iy = 1, this%inny
2242 DO ix = 1, this%innx
2243 point = georef_coord_new(x=lin%dim%lon(ix,iy), y=lin%dim%lat(ix,iy))
2244 DO n = 1, this%trans%poly%arraysize
2245 IF (
inside(point, this%trans%poly%array(n)))
THEN 2249 this%outnx = this%outnx + 1
2251 this%point_index(ix,iy) = n
2260 IF (this%outnx <= 0)
THEN 2262 "metamorphosis:poly: no points inside polygons")
2265 CALL vol7d_alloc(v7d_out, nana=this%outnx)
2268 DO iy = 1, this%inny
2269 DO ix = 1, this%innx
2270 IF (
c_e(this%point_index(ix,iy)))
THEN 2272 CALL init(v7d_out%ana(n), &
2273 lon=lin%dim%lon(ix,iy), lat=lin%dim%lat(ix,iy))
2280 ELSE IF (this%trans%sub_type ==
'mask' )
THEN 2282 IF (.NOT.
PRESENT(maskgrid))
THEN 2284 'grid_transform_init maskgrid argument missing for metamorphosis:mask transformation')
2289 IF (this%innx /=
SIZE(maskgrid,1) .OR. this%inny /=
SIZE(maskgrid,2))
THEN 2291 'grid_transform_init mask non conformal with input field')
2293 'mask: '//t2c(
SIZE(maskgrid,1))//
'x'//t2c(
SIZE(maskgrid,2))// &
2294 ' input field:'//t2c(this%innx)//
'x'//t2c(this%inny))
2300 CALL gen_mask_class()
2312 DO iy = 1, this%inny
2313 DO ix = 1, this%innx
2314 IF (
c_e(maskgrid(ix,iy)))
THEN 2315 IF (maskgrid(ix,iy) <= lmaskbounds(nmaskarea+1))
THEN 2316 DO n = nmaskarea, 1, -1
2317 IF (maskgrid(ix,iy) > lmaskbounds(n))
THEN 2321 this%outnx = this%outnx + 1
2323 this%point_index(ix,iy) = n
2334 IF (this%outnx <= 0)
THEN 2336 "grid_transform_init no points inside mask for metamorphosis:mask transformation")
2341 "points in subarea "//t2c(n)//
": "// &
2342 t2c(count(this%point_index(:,:) == n)))
2345 CALL vol7d_alloc(v7d_out, nana=this%outnx)
2348 DO iy = 1, this%inny
2349 DO ix = 1, this%innx
2350 IF (
c_e(this%point_index(ix,iy)))
THEN 2352 CALL init(v7d_out%ana(n),lon=lin%dim%lon(ix,iy),lat=lin%dim%lat(ix,iy))
2359 ELSE IF (this%trans%sub_type ==
'index')
THEN 2360 this%outnx =
SIZE(v7d_out%ana)
2365 IF (any(
c_e(lin%dim%lon)))
THEN 2366 DO n = 1,
SIZE(v7d_out%ana)
2367 iy = (v7d_out%volanai(n,1,1) - 1)/this%innx + 1
2368 ix = v7d_out%volanai(n,1,1) - (iy-1)*this%innx
2369 this%point_index(ix,iy) = v7d_out%volanai(n,1,1)
2370 CALL init(v7d_out%ana(n), &
2371 lon=lin%dim%lon(ix,iy), lat=lin%dim%lat(ix,iy))
2374 DO n = 1,
SIZE(v7d_out%ana)
2375 iy = (v7d_out%volanai(n,1,1) - 1)/this%innx + 1
2376 ix = v7d_out%volanai(n,1,1) - (iy-1)*this%innx
2377 this%point_index(ix,iy) = v7d_out%volanai(n,1,1)
2387 SUBROUTINE gen_mask_class()
2388 REAL :: startmaskclass, mmin, mmax
2391 IF (
PRESENT(maskbounds))
THEN 2392 nmaskarea =
SIZE(maskbounds) - 1
2393 IF (nmaskarea > 0)
THEN 2394 lmaskbounds = maskbounds
2396 ELSE IF (nmaskarea == 0)
THEN 2398 'only one value provided for maskbounds, '//t2c(maskbounds(1)) &
2399 //
', it will be ignored')
2401 'at least 2 values are required for maskbounds')
2405 mmin = minval(maskgrid, mask=
c_e(maskgrid))
2406 mmax = maxval(maskgrid, mask=
c_e(maskgrid))
2408 nmaskarea = int(mmax - mmin + 1.5)
2409 startmaskclass = mmin - 0.5
2411 ALLOCATE(lmaskbounds(nmaskarea+1))
2412 lmaskbounds(:) = (/(startmaskclass+
REAL(i),i=0,nmaskarea)/)
2415 'maskinter, '//t2c(nmaskarea)//
' subareas defined, with boundaries:')
2416 DO i = 1,
SIZE(lmaskbounds)
2418 'maskinter '//t2c(i)//
' '//t2c(lmaskbounds(i)))
2422 END SUBROUTINE gen_mask_class
2424 END SUBROUTINE grid_transform_grid_vol7d_init
2445 SUBROUTINE grid_transform_vol7d_grid_init(this, trans, v7d_in, out, categoryappend)
2446 TYPE(grid_transform),
INTENT(out) :: this
2447 TYPE(transform_def),
INTENT(in) :: trans
2448 TYPE(vol7d),
INTENT(in) :: v7d_in
2449 TYPE(griddim_def),
INTENT(in) :: out
2450 character(len=*),
INTENT(in),
OPTIONAL :: categoryappend
2453 DOUBLE PRECISION :: xmin, xmax, ymin, ymax, lonref
2454 DOUBLE PRECISION,
ALLOCATABLE :: lon(:,:),lat(:,:)
2455 TYPE(griddim_def) :: lout
2458 CALL grid_transform_init_common(this, trans, categoryappend)
2463 IF (this%trans%trans_type ==
'inter')
THEN 2465 IF ( this%trans%sub_type ==
'linear' )
THEN 2467 this%innx=
SIZE(v7d_in%ana)
2469 ALLOCATE(lon(this%innx,1),lat(this%innx,1))
2470 ALLOCATE(this%inter_xp(this%innx,this%inny),this%inter_yp(this%innx,this%inny))
2471 CALL getval(v7d_in%ana(:)%coord,lon=lon(:,1),lat=lat(:,1))
2473 CALL copy (out, lout)
2475 lonref = 0.5d0*(maxval(lon(:,1), mask=
c_e(lon(:,1))) + minval(lon(:,1), mask=
c_e(lon(:,1))))
2476 CALL griddim_set_central_lon(lout, lonref)
2478 CALL get_val(lout, nx=nx, ny=ny)
2481 ALLOCATE(this%inter_x(this%outnx,this%outny),this%inter_y(this%outnx,this%outny))
2483 CALL get_val(lout, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
2484 CALL proj(lout, lon, lat, this%inter_xp, this%inter_yp)
2485 CALL griddim_gen_coord(lout, this%inter_x, this%inter_y)
2494 ELSE IF (this%trans%trans_type ==
'boxinter')
THEN 2496 this%innx=
SIZE(v7d_in%ana)
2499 ALLOCATE(lon(this%innx,1),lat(this%innx,1))
2500 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
2501 this%inter_index_y(this%innx,this%inny))
2503 CALL getval(v7d_in%ana(:)%coord,lon=lon(:,1),lat=lat(:,1))
2505 CALL copy (out, lout)
2507 lonref = 0.5d0*(maxval(lon(:,1), mask=
c_e(lon(:,1))) + minval(lon(:,1), mask=
c_e(lon(:,1))))
2508 CALL griddim_set_central_lon(lout, lonref)
2510 CALL get_val(lout, nx=this%outnx, ny=this%outny, &
2511 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
2514 IF (.NOT.
c_e(this%trans%area_info%boxdx)) &
2515 CALL get_val(out, dx=this%trans%area_info%boxdx)
2516 IF (.NOT.
c_e(this%trans%area_info%boxdy)) &
2517 CALL get_val(out, dx=this%trans%area_info%boxdy)
2519 this%trans%area_info%boxdx = this%trans%area_info%boxdx*0.5d0
2520 this%trans%area_info%boxdy = this%trans%area_info%boxdy*0.5d0
2523 CALL this%find_index(lout, .true., &
2524 this%outnx, this%outny, xmin, xmax, ymin, ymax, &
2525 lon, lat, .false., &
2526 this%inter_index_x, this%inter_index_y)
2535 END SUBROUTINE grid_transform_vol7d_grid_init
2572 SUBROUTINE grid_transform_vol7d_vol7d_init(this, trans, v7d_in, v7d_out, &
2573 maskbounds, categoryappend)
2574 TYPE(grid_transform),
INTENT(out) :: this
2575 TYPE(transform_def),
INTENT(in) :: trans
2576 TYPE(vol7d),
INTENT(in) :: v7d_in
2577 TYPE(vol7d),
INTENT(inout) :: v7d_out
2578 REAL,
INTENT(in),
OPTIONAL :: maskbounds(:)
2579 CHARACTER(len=*),
INTENT(in),
OPTIONAL :: categoryappend
2582 DOUBLE PRECISION,
ALLOCATABLE :: lon(:), lat(:)
2584 DOUBLE PRECISION :: lon1, lat1
2585 TYPE(georef_coord) :: point
2588 CALL grid_transform_init_common(this, trans, categoryappend)
2593 IF (this%trans%trans_type ==
'inter')
THEN 2595 IF ( this%trans%sub_type ==
'linear' )
THEN 2597 CALL vol7d_alloc_vol(v7d_out)
2598 this%outnx=
SIZE(v7d_out%ana)
2601 this%innx=
SIZE(v7d_in%ana)
2604 ALLOCATE(this%inter_xp(this%innx,this%inny),this%inter_yp(this%innx,this%inny))
2605 ALLOCATE(this%inter_x(this%outnx,this%outny),this%inter_y(this%outnx,this%outny))
2607 CALL getval(v7d_in%ana(:)%coord,lon=this%inter_xp(:,1),lat=this%inter_yp(:,1))
2608 CALL getval(v7d_out%ana(:)%coord,lon=this%inter_x(:,1),lat=this%inter_y(:,1))
2614 ELSE IF (this%trans%trans_type ==
'polyinter')
THEN 2616 this%innx=
SIZE(v7d_in%ana)
2619 ALLOCATE(this%inter_index_x(this%innx,this%inny), &
2620 this%inter_index_y(this%innx,this%inny))
2621 this%inter_index_x(:,:) = imiss
2622 this%inter_index_y(:,:) = 1
2624 DO i = 1,
SIZE(v7d_in%ana)
2626 CALL getval(v7d_in%ana(i)%coord,lon=lon1,lat=lat1)
2627 point = georef_coord_new(x=lon1, y=lat1)
2629 DO n = 1, this%trans%poly%arraysize
2630 IF (
inside(point, this%trans%poly%array(n)))
THEN 2631 this%inter_index_x(i,1) = n
2637 this%outnx=this%trans%poly%arraysize
2639 CALL vol7d_alloc(v7d_out, nana=this%outnx)
2643 CALL poly_to_coordinates(this%trans%poly, v7d_out)
2647 ELSE IF (this%trans%trans_type ==
'metamorphosis')
THEN 2650 this%innx =
SIZE(v7d_in%ana)
2653 ALLOCATE(this%point_index(this%innx,this%inny))
2654 this%point_index(:,:) = imiss
2656 IF (this%trans%sub_type ==
'all' )
THEN 2658 CALL metamorphosis_all_setup()
2660 ELSE IF (this%trans%sub_type ==
'coordbb' )
THEN 2662 ALLOCATE(lon(this%innx),lat(this%innx))
2667 CALL getval(v7d_in%ana(:)%coord,lon=lon,lat=lat)
2670 IF (lon(i) > this%trans%rect_coo%ilon .AND. &
2671 lon(i) < this%trans%rect_coo%flon .AND. &
2672 lat(i) > this%trans%rect_coo%ilat .AND. &
2673 lat(i) < this%trans%rect_coo%flat)
THEN 2674 this%outnx = this%outnx + 1
2675 this%point_index(i,1) = this%outnx
2679 IF (this%outnx <= 0)
THEN 2681 "metamorphosis:coordbb: no points inside bounding box "//&
2682 trim(
to_char(this%trans%rect_coo%ilon))//
","// &
2683 trim(
to_char(this%trans%rect_coo%flon))//
","// &
2684 trim(
to_char(this%trans%rect_coo%ilat))//
","// &
2685 trim(
to_char(this%trans%rect_coo%flat)))
2688 CALL vol7d_alloc(v7d_out, nana=this%outnx)
2693 IF (
c_e(this%point_index(i,1)))
THEN 2695 CALL init(v7d_out%ana(n),lon=lon(i),lat=lat(i))
2698 DEALLOCATE(lon, lat)
2702 ELSE IF (this%trans%sub_type ==
'poly' )
THEN 2709 CALL getval(v7d_in%ana(i)%coord,lon=lon1,lat=lat1)
2710 point = georef_coord_new(x=lon1, y=lat1)
2711 DO n = 1, this%trans%poly%arraysize
2712 IF (
inside(point, this%trans%poly%array(n)))
THEN 2713 this%outnx = this%outnx + 1
2714 this%point_index(i,1) = n
2721 IF (this%outnx <= 0)
THEN 2723 "metamorphosis:poly: no points inside polygons")
2726 CALL vol7d_alloc(v7d_out, nana=this%outnx)
2731 IF (
c_e(this%point_index(i,1)))
THEN 2734 CALL getval(v7d_in%ana(i)%coord,lon=lon1,lat=lat1)
2735 CALL init(v7d_out%ana(n),lon=lon1,lat=lat1)
2741 ELSE IF (this%trans%sub_type ==
'setinvalidto' )
THEN 2743 IF (.NOT.
PRESENT(maskbounds))
THEN 2745 'grid_transform_init maskbounds missing for metamorphosis:'// &
2746 trim(this%trans%sub_type)//
' transformation')
2748 ELSE IF (
SIZE(maskbounds) < 1)
THEN 2750 'grid_transform_init maskbounds empty for metamorphosis:'// &
2751 trim(this%trans%sub_type)//
' transformation')
2754 this%val1 = maskbounds(1)
2757 "grid_transform_init setting invalid data to "//t2c(this%val1))
2761 CALL metamorphosis_all_setup()
2763 ELSE IF (this%trans%sub_type ==
'settoinvalid' )
THEN 2765 IF (.NOT.
PRESENT(maskbounds))
THEN 2767 'grid_transform_init maskbounds missing for metamorphosis:'// &
2768 trim(this%trans%sub_type)//
' transformation')
2771 ELSE IF (
SIZE(maskbounds) < 2)
THEN 2773 'grid_transform_init maskbounds must have at least 2 elements for metamorphosis:'// &
2774 trim(this%trans%sub_type)//
' transformation')
2778 this%val1 = maskbounds(1)
2779 this%val2 = maskbounds(
SIZE(maskbounds))
2782 "grid_transform_init setting to invalid interval ]"//t2c(this%val1)//
','// &
2783 t2c(this%val2)//
']')
2787 CALL metamorphosis_all_setup()
2796 SUBROUTINE metamorphosis_all_setup()
2798 this%outnx =
SIZE(v7d_in%ana)
2800 this%point_index(:,1) = (/(i,i=1,this%innx)/)
2801 CALL vol7d_alloc(v7d_out, nana=
SIZE(v7d_in%ana))
2802 v7d_out%ana = v7d_in%ana
2806 END SUBROUTINE metamorphosis_all_setup
2808 END SUBROUTINE grid_transform_vol7d_vol7d_init
2812 SUBROUTINE grid_transform_init_common(this, trans, categoryappend)
2813 TYPE(grid_transform),
INTENT(inout) :: this
2814 TYPE(transform_def),
INTENT(in) :: trans
2815 CHARACTER(len=*),
INTENT(in),
OPTIONAL :: categoryappend
2817 CHARACTER(len=512) :: a_name
2819 IF (
PRESENT(categoryappend))
THEN 2820 CALL l4f_launcher(a_name,a_name_append=trim(subcategory)//
"."// &
2821 trim(categoryappend))
2823 CALL l4f_launcher(a_name,a_name_append=trim(subcategory))
2825 this%category=l4f_category_get_handle(a_name)
2833 END SUBROUTINE grid_transform_init_common
2837 SUBROUTINE poly_to_coordinates(poly, v7d_out)
2838 TYPE(arrayof_georef_coord_array),
intent(in) :: poly
2839 TYPE(vol7d),
INTENT(inout) :: v7d_out
2842 DOUBLE PRECISION,
ALLOCATABLE :: lon(:), lat(:)
2844 DO n = 1, poly%arraysize
2845 CALL getval(poly%array(n), x=lon, y=lat)
2846 sz = min(
SIZE(lon),
SIZE(lat))
2847 IF (lon(1) == lon(sz) .AND. lat(1) == lat(sz))
THEN 2853 END SUBROUTINE poly_to_coordinates
2858 SUBROUTINE grid_transform_delete(this)
2859 TYPE(grid_transform),
INTENT(inout) :: this
2876 if (
associated(this%inter_index_x))
deallocate (this%inter_index_x)
2877 if (
associated(this%inter_index_y))
deallocate (this%inter_index_y)
2878 if (
associated(this%inter_index_z))
deallocate (this%inter_index_z)
2879 if (
associated(this%point_index))
deallocate (this%point_index)
2881 if (
associated(this%inter_x))
deallocate (this%inter_x)
2882 if (
associated(this%inter_y))
deallocate (this%inter_y)
2884 if (
associated(this%inter_xp))
deallocate (this%inter_xp)
2885 if (
associated(this%inter_yp))
deallocate (this%inter_yp)
2886 if (
associated(this%inter_zp))
deallocate (this%inter_zp)
2887 if (
associated(this%vcoord_in))
deallocate (this%vcoord_in)
2888 if (
associated(this%vcoord_out))
deallocate (this%vcoord_out)
2889 if (
associated(this%point_mask))
deallocate (this%point_mask)
2890 if (
associated(this%stencil))
deallocate (this%stencil)
2891 if (
associated(this%output_level_auto))
deallocate (this%output_level_auto)
2892 IF (
ALLOCATED(this%coord_3d_in))
DEALLOCATE(this%coord_3d_in)
2893 this%valid = .false.
2896 call l4f_category_delete(this%category)
2898 END SUBROUTINE grid_transform_delete
2905 SUBROUTINE grid_transform_get_val(this, output_level_auto, point_mask, &
2906 point_index, output_point_index, levshift, levused)
2907 TYPE(grid_transform),
INTENT(in) :: this
2908 TYPE(vol7d_level),
POINTER,
OPTIONAL :: output_level_auto(:)
2909 LOGICAL,
INTENT(out),
ALLOCATABLE,
OPTIONAL :: point_mask(:)
2910 INTEGER,
INTENT(out),
ALLOCATABLE,
OPTIONAL :: point_index(:)
2911 INTEGER,
INTENT(out),
ALLOCATABLE,
OPTIONAL :: output_point_index(:)
2912 INTEGER,
INTENT(out),
OPTIONAL :: levshift
2913 INTEGER,
INTENT(out),
OPTIONAL :: levused
2917 IF (
PRESENT(output_level_auto)) output_level_auto => this%output_level_auto
2918 IF (
PRESENT(point_mask))
THEN 2919 IF (
ASSOCIATED(this%point_index))
THEN 2920 point_mask =
c_e(reshape(this%point_index, (/
SIZE(this%point_index)/)))
2923 IF (
PRESENT(point_index))
THEN 2924 IF (
ASSOCIATED(this%point_index))
THEN 2925 point_index = reshape(this%point_index, (/
SIZE(this%point_index)/))
2928 IF (
PRESENT(output_point_index))
THEN 2929 IF (
ASSOCIATED(this%point_index))
THEN 2931 output_point_index = pack(this%point_index(:,:),
c_e(this%point_index))
2932 ELSE IF (this%trans%trans_type ==
'polyinter' .OR. &
2933 this%trans%trans_type ==
'maskinter')
THEN 2935 output_point_index = (/(i,i=1,this%outnx)/)
2938 IF (
PRESENT(levshift)) levshift = this%levshift
2939 IF (
PRESENT(levused)) levused = this%levused
2941 END SUBROUTINE grid_transform_get_val
2946 FUNCTION grid_transform_c_e(this)
2947 TYPE(grid_transform),
INTENT(in) :: this
2948 LOGICAL :: grid_transform_c_e
2950 grid_transform_c_e = this%valid
2952 END FUNCTION grid_transform_c_e
2964 RECURSIVE SUBROUTINE grid_transform_compute(this, field_in, field_out, var, &
2966 TYPE(grid_transform),
INTENT(in),
TARGET :: this
2967 REAL,
INTENT(in) :: field_in(:,:,:)
2968 REAL,
INTENT(out) :: field_out(:,:,:)
2969 TYPE(vol7d_var),
INTENT(in),
OPTIONAL :: var
2970 REAL,
INTENT(in),
OPTIONAL,
TARGET :: coord_3d_in(:,:,:)
2971 LOGICAL,
INTENT(in),
OPTIONAL :: zlist(:)
2973 INTEGER :: i, j, k, l, m, s, ii, jj, ie, je, n, navg, kk, kkcache, kkup, kkdown, &
2974 kfound, kfoundin, inused, i1, i2, j1, j2, np, ns, ix, iy
2975 INTEGER,
ALLOCATABLE :: nval(:,:)
2976 REAL :: z1,z2,z3,z4,z(4)
2977 DOUBLE PRECISION :: x1,x3,y1,y3,xp,yp, disttmp, dist
2978 INTEGER :: innx, inny, innz, outnx, outny, outnz, vartype, nearcount
2979 REAL,
ALLOCATABLE :: coord_in(:)
2980 LOGICAL,
ALLOCATABLE :: mask_in(:)
2981 REAL,
ALLOCATABLE :: val_in(:), field_tmp(:,:,:)
2982 REAL,
POINTER :: coord_3d_in_act(:,:,:)
2983 TYPE(grid_transform) :: likethis
2984 LOGICAL :: alloc_coord_3d_in_act, nm1, optsearch, farenough
2985 CHARACTER(len=4) :: env_var
2986 LOGICAL,
ALLOCATABLE :: lzlist(:)
2989 CALL l4f_category_log(this%category,l4f_debug,
"start grid_transform_compute")
2992 field_out(:,:,:) = rmiss
2994 IF (.NOT.this%valid)
THEN 2996 "refusing to perform a non valid transformation")
3000 IF (this%recur)
THEN 3003 "recursive transformation in grid_transform_compute")
3006 IF (this%trans%trans_type ==
'polyinter')
THEN 3008 likethis%recur = .false.
3009 likethis%outnx = this%trans%poly%arraysize
3011 ALLOCATE(field_tmp(this%trans%poly%arraysize,1,
SIZE(field_out,3)))
3012 CALL grid_transform_compute(likethis, field_in, field_tmp, var, coord_3d_in, zlist)
3014 DO k = 1,
SIZE(field_out,3)
3017 IF (
c_e(this%inter_index_x(i,j)))
THEN 3018 field_out(i,j,k) = field_tmp(this%inter_index_x(i,j),this%inter_index_y(i,j),k)
3023 DEALLOCATE(field_tmp)
3030 IF (
PRESENT(var))
THEN 3031 vartype = vol7d_vartype(var)
3034 innx =
SIZE(field_in,1); inny =
SIZE(field_in,2); innz =
SIZE(field_in,3)
3035 outnx =
SIZE(field_out,1); outny =
SIZE(field_out,2); outnz =
SIZE(field_out,3)
3036 ALLOCATE(lzlist(innz))
3037 IF (
PRESENT(zlist))
THEN 3038 lzlist(:) = zlist(:)
3044 IF (this%trans%trans_type ==
'vertint')
THEN 3046 IF (innz /= this%innz)
THEN 3048 CALL l4f_category_log(this%category,l4f_error,
"inconsistent input shape: "//&
3049 t2c(this%innz)//
" /= "//t2c(innz))
3054 IF (outnz /= this%outnz)
THEN 3056 CALL l4f_category_log(this%category,l4f_error,
"inconsistent output shape: "//&
3057 t2c(this%outnz)//
" /= "//t2c(outnz))
3062 IF (innx /= outnx .OR. inny /= outny)
THEN 3064 CALL l4f_category_log(this%category,l4f_error,
"inconsistent hor. sizes: "//&
3065 t2c(innx)//
","//t2c(inny)//
" /= "//&
3066 t2c(outnx)//
","//t2c(outny))
3073 IF (innx /= this%innx .OR. inny /= this%inny)
THEN 3075 CALL l4f_category_log(this%category,l4f_error,
"inconsistent input shape: "//&
3076 t2c(this%innx)//
","//t2c(this%inny)//
" /= "//&
3077 t2c(innx)//
","//t2c(inny))
3082 IF (outnx /= this%outnx .OR. outny /= this%outny)
THEN 3084 CALL l4f_category_log(this%category,l4f_error,
"inconsistent output shape: "//&
3085 t2c(this%outnx)//
","//t2c(this%outny)//
" /= "//&
3086 t2c(outnx)//
","//t2c(outny))
3091 IF (innz /= outnz)
THEN 3093 CALL l4f_category_log(this%category,l4f_error,
"inconsistent vert. sizes: "//&
3094 t2c(innz)//
" /= "//t2c(outnz))
3103 "start grid_transform_compute "//trim(this%trans%trans_type)//
':'// &
3104 trim(this%trans%sub_type))
3107 IF (this%trans%trans_type ==
'zoom')
THEN 3109 field_out(this%outinx:this%outfnx, &
3110 this%outiny:this%outfny,:) = &
3111 field_in(this%iniox:this%infox, &
3112 this%inioy:this%infoy,:)
3114 ELSE IF (this%trans%trans_type ==
'boxregrid')
THEN 3116 IF (this%trans%sub_type ==
'average')
THEN 3117 IF (vartype == var_dir360)
THEN 3119 IF (.NOT.lzlist(k)) cycle
3121 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3122 je = j+this%trans%box_info%npy-1
3125 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3126 ie = i+this%trans%box_info%npx-1
3128 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3130 field_out(ii,jj,k) = find_prevailing_direction(field_in(i:ie,j:je,k), &
3139 IF (.NOT.lzlist(k)) cycle
3141 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3142 je = j+this%trans%box_info%npy-1
3145 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3146 ie = i+this%trans%box_info%npx-1
3148 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3150 field_out(ii,jj,k) = sum(field_in(i:ie,j:je,k), &
3151 mask=(field_in(i:ie,j:je,k) /= rmiss))/navg
3159 ELSE IF (this%trans%sub_type ==
'stddev' .OR. &
3160 this%trans%sub_type ==
'stddevnm1')
THEN 3162 IF (this%trans%sub_type ==
'stddev')
THEN 3168 navg = this%trans%box_info%npx*this%trans%box_info%npy
3170 IF (.NOT.lzlist(k)) cycle
3172 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3173 je = j+this%trans%box_info%npy-1
3176 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3177 ie = i+this%trans%box_info%npx-1
3180 reshape(field_in(i:ie,j:je,k),(/navg/)), nm1=nm1)
3185 ELSE IF (this%trans%sub_type ==
'max')
THEN 3187 IF (.NOT.lzlist(k)) cycle
3189 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3190 je = j+this%trans%box_info%npy-1
3193 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3194 ie = i+this%trans%box_info%npx-1
3196 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3198 field_out(ii,jj,k) = maxval(field_in(i:ie,j:je,k), &
3199 mask=(field_in(i:ie,j:je,k) /= rmiss))
3205 ELSE IF (this%trans%sub_type ==
'min')
THEN 3207 IF (.NOT.lzlist(k)) cycle
3209 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3210 je = j+this%trans%box_info%npy-1
3213 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3214 ie = i+this%trans%box_info%npx-1
3216 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3218 field_out(ii,jj,k) = minval(field_in(i:ie,j:je,k), &
3219 mask=(field_in(i:ie,j:je,k) /= rmiss))
3225 ELSE IF (this%trans%sub_type ==
'percentile')
THEN 3227 navg = this%trans%box_info%npx*this%trans%box_info%npy
3229 IF (.NOT.lzlist(k)) cycle
3231 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3232 je = j+this%trans%box_info%npy-1
3235 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3236 ie = i+this%trans%box_info%npx-1
3239 reshape(field_in(i:ie,j:je,k),(/navg/)), &
3240 (/
REAL(this%trans%stat_info%percentile)/))
3245 ELSE IF (this%trans%sub_type ==
'frequency')
THEN 3248 IF (.NOT.lzlist(k)) cycle
3250 DO j = 1, this%inny - this%trans%box_info%npy + 1, this%trans%box_info%npy
3251 je = j+this%trans%box_info%npy-1
3254 DO i = 1, this%innx - this%trans%box_info%npx + 1, this%trans%box_info%npx
3255 ie = i+this%trans%box_info%npx-1
3257 navg = count(field_in(i:ie,j:je,k) /= rmiss)
3259 field_out(ii,jj,k) = sum(interval_info_valid( &
3260 this%trans%interval_info, field_in(i:ie,j:je,k)), &
3261 mask=(field_in(i:ie,j:je,k) /= rmiss))/navg
3269 ELSE IF (this%trans%trans_type ==
'inter')
THEN 3271 IF (this%trans%sub_type ==
'near')
THEN 3274 IF (.NOT.lzlist(k)) cycle
3275 DO j = 1, this%outny
3276 DO i = 1, this%outnx
3278 IF (
c_e(this%inter_index_x(i,j))) field_out(i,j,k) = &
3279 field_in(this%inter_index_x(i,j),this%inter_index_y(i,j),k)
3285 ELSE IF (this%trans%sub_type ==
'bilin')
THEN 3288 IF (.NOT.lzlist(k)) cycle
3289 DO j = 1, this%outny
3290 DO i = 1, this%outnx
3292 IF (
c_e(this%inter_index_x(i,j)))
THEN 3294 z1=field_in(this%inter_index_x(i,j),this%inter_index_y(i,j),k)
3295 z2=field_in(this%inter_index_x(i,j)+1,this%inter_index_y(i,j),k)
3296 z3=field_in(this%inter_index_x(i,j)+1,this%inter_index_y(i,j)+1,k)
3297 z4=field_in(this%inter_index_x(i,j),this%inter_index_y(i,j)+1,k)
3299 IF (
c_e(z1) .AND.
c_e(z2) .AND.
c_e(z3) .AND.
c_e(z4))
THEN 3301 x1=this%inter_x(this%inter_index_x(i,j),this%inter_index_y(i,j))
3302 y1=this%inter_y(this%inter_index_x(i,j),this%inter_index_y(i,j))
3303 x3=this%inter_x(this%inter_index_x(i,j)+1,this%inter_index_y(i,j)+1)
3304 y3=this%inter_y(this%inter_index_x(i,j)+1,this%inter_index_y(i,j)+1)
3306 xp=this%inter_xp(i,j)
3307 yp=this%inter_yp(i,j)
3309 field_out(i,j,k) = hbilin(z1,z2,z3,z4,x1,y1,x3,y3,xp,yp)
3317 ELSE IF (this%trans%sub_type ==
'shapiro_near')
THEN 3319 IF (.NOT.lzlist(k)) cycle
3320 DO j = 1, this%outny
3321 DO i = 1, this%outnx
3323 IF (
c_e(this%inter_index_x(i,j)))
THEN 3325 IF(this%inter_index_x(i,j)-1>0)
THEN 3326 z(1) = field_in(this%inter_index_x(i,j)-1,this%inter_index_y(i,j) ,k)
3330 IF(this%inter_index_x(i,j)+1<=this%outnx)
THEN 3331 z(3)=field_in(this%inter_index_x(i,j)+1,this%inter_index_y(i,j) ,k)
3335 IF(this%inter_index_y(i,j)+1<=this%outny)
THEN 3336 z(2)=field_in(this%inter_index_x(i,j) ,this%inter_index_y(i,j)+1,k)
3340 IF(this%inter_index_y(i,j)-1>0)
THEN 3341 z(4)=field_in(this%inter_index_x(i,j), this%inter_index_y(i,j)-1,k)
3345 field_out(i,j,k) = shapiro(z,field_in(this%inter_index_x(i,j),this%inter_index_y(i,j),k))
3354 ELSE IF (this%trans%trans_type ==
'intersearch')
THEN 3357 likethis%trans%trans_type =
'inter' 3358 CALL grid_transform_compute(likethis, field_in, field_out, var, coord_3d_in, zlist)
3359 CALL getenv(
'LIBSIM_DISABLEOPTSEARCH', env_var)
3360 optsearch = len_trim(env_var) == 0
3363 IF (.NOT.lzlist(k)) cycle
3364 IF ((.NOT.all(
c_e(field_out(:,:,k)))) .AND. (any(
c_e(field_in(:,:,k)))))
THEN 3365 DO j = 1, this%outny
3366 DO i = 1, this%outnx
3367 IF (.NOT.
c_e(field_out(i,j,k)))
THEN 3371 ix = this%inter_index_x(i,j)
3372 iy = this%inter_index_y(i,j)
3373 DO s = 0, max(this%innx, this%inny)
3375 DO m = iy-s, iy+s, max(2*s, 1)
3376 IF (m < 1 .OR. m > this%inny) cycle
3377 DO l = max(1, ix-s), min(this%innx, ix+s)
3378 disttmp = (this%inter_xp(i,j) - this%inter_x(l,m))**2 + (this%inter_yp(i,j) - this%inter_y(l,m))**2
3379 IF (
c_e(field_in(l,m,k)))
THEN 3380 IF (disttmp <
dist)
THEN 3382 field_out(i,j,k) = field_in(l,m,k)
3384 ELSE IF (disttmp ==
dist)
THEN 3385 field_out(i,j,k) = field_out(i,j,k) + field_in(l,m,k)
3386 nearcount = nearcount + 1
3389 IF (disttmp <
dist) farenough = .false.
3392 DO m = max(1, iy-s+1), min(this%inny, iy+s-1)
3393 DO l = ix-s, ix+s, 2*s
3394 IF (l < 1 .OR. l > this%innx) cycle
3395 disttmp = (this%inter_xp(i,j) - this%inter_x(l,m))**2 + (this%inter_yp(i,j) - this%inter_y(l,m))**2
3396 IF (
c_e(field_in(l,m,k)))
THEN 3397 IF (disttmp <
dist)
THEN 3399 field_out(i,j,k) = field_in(l,m,k)
3401 ELSE IF (disttmp ==
dist)
THEN 3402 field_out(i,j,k) = field_out(i,j,k) + field_in(l,m,k)
3403 nearcount = nearcount + 1
3406 IF (disttmp <
dist) farenough = .false.
3409 IF (s > 0 .AND. farenough)
EXIT 3414 IF (
c_e(field_in(l,m,k)))
THEN 3415 disttmp = (this%inter_xp(i,j) - this%inter_x(l,m))**2 + (this%inter_yp(i,j) - this%inter_y(l,m))**2
3416 IF (disttmp <
dist)
THEN 3418 field_out(i,j,k) = field_in(l,m,k)
3420 ELSE IF (disttmp ==
dist)
THEN 3421 field_out(i,j,k) = field_out(i,j,k) + field_in(l,m,k)
3422 nearcount = nearcount + 1
3429 IF (nearcount > 1) field_out(i,j,k) = field_out(i,j,k)/nearcount
3436 ELSE IF (this%trans%trans_type ==
'boxinter' &
3437 .OR. this%trans%trans_type ==
'polyinter' &
3438 .OR. this%trans%trans_type ==
'maskinter')
THEN 3440 IF (this%trans%sub_type ==
'average')
THEN 3442 IF (vartype == var_dir360)
THEN 3444 IF (.NOT.lzlist(k)) cycle
3445 DO j = 1, this%outny
3446 DO i = 1, this%outnx
3447 field_out(i,j,k) = find_prevailing_direction(field_in(:,:,k), &
3449 mask=this%inter_index_x(:,:) == i .AND. this%inter_index_y(:,:) == j)
3455 ALLOCATE(nval(this%outnx, this%outny))
3456 field_out(:,:,:) = 0.0
3458 IF (.NOT.lzlist(k)) cycle
3462 IF (
c_e(this%inter_index_x(i,j)) .AND.
c_e(field_in(i,j,k)))
THEN 3463 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3464 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) + &
3466 nval(this%inter_index_x(i,j),this%inter_index_y(i,j)) = &
3467 nval(this%inter_index_x(i,j),this%inter_index_y(i,j)) + 1
3471 WHERE (nval(:,:) /= 0)
3472 field_out(:,:,k) = field_out(:,:,k)/nval(:,:)
3474 field_out(:,:,k) = rmiss
3480 ELSE IF (this%trans%sub_type ==
'stddev' .OR. &
3481 this%trans%sub_type ==
'stddevnm1')
THEN 3483 IF (this%trans%sub_type ==
'stddev')
THEN 3489 IF (.NOT.lzlist(k)) cycle
3490 DO j = 1, this%outny
3491 DO i = 1, this%outnx
3494 reshape(field_in(:,:,k), (/
SIZE(field_in(:,:,k))/)), &
3495 mask=reshape((this%inter_index_x == i .AND. &
3496 this%inter_index_y == j), (/
SIZE(field_in(:,:,k))/)), nm1=nm1)
3501 ELSE IF (this%trans%sub_type ==
'max')
THEN 3504 IF (.NOT.lzlist(k)) cycle
3507 IF (
c_e(this%inter_index_x(i,j)) .AND.
c_e(field_in(i,j,k)))
THEN 3508 IF (
c_e(field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k)))
THEN 3509 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3510 max(field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k), &
3513 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3522 ELSE IF (this%trans%sub_type ==
'min')
THEN 3525 IF (.NOT.lzlist(k)) cycle
3528 IF (
c_e(this%inter_index_x(i,j)) .AND.
c_e(field_in(i,j,k)))
THEN 3529 IF (
c_e(field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k)))
THEN 3530 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3531 min(field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k), &
3534 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3542 ELSE IF (this%trans%sub_type ==
'percentile')
THEN 3545 IF (.NOT.lzlist(k)) cycle
3546 DO j = 1, this%outny
3547 DO i = 1, this%outnx
3550 reshape(field_in(:,:,k), (/
SIZE(field_in(:,:,k))/)), &
3551 (/
REAL(this%trans%stat_info%percentile)/), &
3552 mask=reshape((this%inter_index_x == i .AND. &
3553 this%inter_index_y == j), (/
SIZE(field_in(:,:,k))/)))
3558 ELSE IF (this%trans%sub_type ==
'frequency')
THEN 3560 ALLOCATE(nval(this%outnx, this%outny))
3562 IF (.NOT.lzlist(k)) cycle
3563 field_out(:,:,k) = 0.0
3567 IF (
c_e(this%inter_index_x(i,j)) .AND.
c_e(field_in(i,j,k)))
THEN 3568 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) = &
3569 field_out(this%inter_index_x(i,j),this%inter_index_y(i,j),k) + &
3570 interval_info_valid(this%trans%interval_info, field_in(i,j,k))
3571 nval(this%inter_index_x(i,j),this%inter_index_y(i,j)) = &
3572 nval(this%inter_index_x(i,j),this%inter_index_y(i,j)) + 1
3576 WHERE (nval(:,:) /= 0)
3577 field_out(:,:,k) = field_out(:,:,k)/nval(:,:)
3579 field_out(:,:,k) = rmiss
3586 ELSE IF (this%trans%trans_type ==
'stencilinter')
THEN 3587 np =
SIZE(this%stencil,1)/2
3588 ns =
SIZE(this%stencil)
3590 IF (this%trans%sub_type ==
'average')
THEN 3592 IF (vartype == var_dir360)
THEN 3594 IF (.NOT.lzlist(k)) cycle
3595 DO j = 1, this%outny
3596 DO i = 1, this%outnx
3597 IF (
c_e(this%inter_index_x(i,j)))
THEN 3598 i1 = this%inter_index_x(i,j) - np
3599 i2 = this%inter_index_x(i,j) + np
3600 j1 = this%inter_index_y(i,j) - np
3601 j2 = this%inter_index_y(i,j) + np
3602 field_out(i,j,k) = find_prevailing_direction(field_in(i1:i2,j1:j2,k), &
3604 mask=this%stencil(:,:))
3615 IF (.NOT.lzlist(k)) cycle
3616 DO j = 1, this%outny
3617 DO i = 1, this%outnx
3618 IF (
c_e(this%inter_index_x(i,j)))
THEN 3619 i1 = this%inter_index_x(i,j) - np
3620 i2 = this%inter_index_x(i,j) + np
3621 j1 = this%inter_index_y(i,j) - np
3622 j2 = this%inter_index_y(i,j) + np
3623 n = count(field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3625 field_out(i,j,k) = sum(field_in(i1:i2,j1:j2,k), &
3626 mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))/n
3635 ELSE IF (this%trans%sub_type ==
'stddev' .OR. &
3636 this%trans%sub_type ==
'stddevnm1')
THEN 3638 IF (this%trans%sub_type ==
'stddev')
THEN 3647 IF (.NOT.lzlist(k)) cycle
3648 DO j = 1, this%outny
3649 DO i = 1, this%outnx
3650 IF (
c_e(this%inter_index_x(i,j)))
THEN 3651 i1 = this%inter_index_x(i,j) - np
3652 i2 = this%inter_index_x(i,j) + np
3653 j1 = this%inter_index_y(i,j) - np
3654 j2 = this%inter_index_y(i,j) + np
3657 reshape(field_in(i1:i2,j1:j2,k), (/ns/)), &
3658 mask=reshape(field_in(i1:i2,j1:j2,k) /= rmiss .AND. &
3659 this%stencil(:,:), (/ns/)), nm1=nm1)
3666 ELSE IF (this%trans%sub_type ==
'max')
THEN 3671 IF (.NOT.lzlist(k)) cycle
3672 DO j = 1, this%outny
3673 DO i = 1, this%outnx
3674 IF (
c_e(this%inter_index_x(i,j)))
THEN 3675 i1 = this%inter_index_x(i,j) - np
3676 i2 = this%inter_index_x(i,j) + np
3677 j1 = this%inter_index_y(i,j) - np
3678 j2 = this%inter_index_y(i,j) + np
3679 n = count(field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3681 field_out(i,j,k) = maxval(field_in(i1:i2,j1:j2,k), &
3682 mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3690 ELSE IF (this%trans%sub_type ==
'min')
THEN 3695 IF (.NOT.lzlist(k)) cycle
3696 DO j = 1, this%outny
3697 DO i = 1, this%outnx
3698 IF (
c_e(this%inter_index_x(i,j)))
THEN 3699 i1 = this%inter_index_x(i,j) - np
3700 i2 = this%inter_index_x(i,j) + np
3701 j1 = this%inter_index_y(i,j) - np
3702 j2 = this%inter_index_y(i,j) + np
3703 n = count(field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3705 field_out(i,j,k) = minval(field_in(i1:i2,j1:j2,k), &
3706 mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3714 ELSE IF (this%trans%sub_type ==
'percentile')
THEN 3719 IF (.NOT.lzlist(k)) cycle
3720 DO j = 1, this%outny
3721 DO i = 1, this%outnx
3722 IF (
c_e(this%inter_index_x(i,j)))
THEN 3723 i1 = this%inter_index_x(i,j) - np
3724 i2 = this%inter_index_x(i,j) + np
3725 j1 = this%inter_index_y(i,j) - np
3726 j2 = this%inter_index_y(i,j) + np
3729 reshape(field_in(i1:i2,j1:j2,k), (/ns/)), &
3730 (/
REAL(this%trans%stat_info%percentile)/), &
3731 mask=reshape(field_in(i1:i2,j1:j2,k) /= rmiss .AND. &
3732 this%stencil(:,:), (/ns/)))
3739 ELSE IF (this%trans%sub_type ==
'frequency')
THEN 3744 IF (.NOT.lzlist(k)) cycle
3745 DO j = 1, this%outny
3746 DO i = 1, this%outnx
3747 IF (
c_e(this%inter_index_x(i,j)))
THEN 3748 i1 = this%inter_index_x(i,j) - np
3749 i2 = this%inter_index_x(i,j) + np
3750 j1 = this%inter_index_y(i,j) - np
3751 j2 = this%inter_index_y(i,j) + np
3752 n = count(field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))
3754 field_out(i,j,k) = sum(interval_info_valid( &
3755 this%trans%interval_info, field_in(i1:i2,j1:j2,k)), &
3756 mask=field_in(i1:i2,j1:j2,k) /= rmiss .AND. this%stencil(:,:))/n
3766 ELSE IF (this%trans%trans_type ==
'maskgen')
THEN 3769 WHERE(
c_e(this%inter_index_x(:,:)))
3770 field_out(:,:,k) =
REAL(this%inter_index_x(:,:))
3774 ELSE IF (this%trans%trans_type ==
'metamorphosis')
THEN 3776 IF (this%trans%sub_type ==
'all')
THEN 3778 field_out(:,:,:) = reshape(field_in(:,:,:), (/this%outnx,this%outny,innz/))
3780 ELSE IF (this%trans%sub_type ==
'coordbb' .OR. this%trans%sub_type ==
'poly' &
3781 .OR. this%trans%sub_type ==
'mask' .OR. this%trans%sub_type ==
'index')
THEN 3784 IF (.NOT.lzlist(k)) cycle
3786 field_out(:,1,k) = pack(field_in(:,:,k),
c_e(this%point_index(:,:)))
3789 ELSE IF (this%trans%sub_type ==
'maskvalid' .OR. &
3790 this%trans%sub_type ==
'maskinvalid')
THEN 3793 IF (.NOT.lzlist(k)) cycle
3794 WHERE (this%point_mask(:,:))
3795 field_out(:,:,k) = field_in(:,:,k)
3799 ELSE IF (this%trans%sub_type ==
'lemaskinvalid')
THEN 3802 IF (.NOT.lzlist(k)) cycle
3803 WHERE (
c_e(field_in(:,:,k)) .AND. field_in(:,:,k) > this%val_mask(:,:))
3804 field_out(:,:,k) = field_in(:,:,k)
3806 field_out(:,:,k) = rmiss
3810 ELSE IF (this%trans%sub_type ==
'ltmaskinvalid')
THEN 3813 IF (.NOT.lzlist(k)) cycle
3814 WHERE (
c_e(field_in(:,:,k)) .AND. field_in(:,:,k) >= this%val_mask(:,:))
3815 field_out(:,:,k) = field_in(:,:,k)
3817 field_out(:,:,k) = rmiss
3821 ELSE IF (this%trans%sub_type ==
'gemaskinvalid')
THEN 3824 IF (.NOT.lzlist(k)) cycle
3825 WHERE (
c_e(field_in(:,:,k)) .AND. field_in(:,:,k) < this%val_mask(:,:))
3826 field_out(:,:,k) = field_in(:,:,k)
3828 field_out(:,:,k) = rmiss
3832 ELSE IF (this%trans%sub_type ==
'gtmaskinvalid')
THEN 3835 IF (.NOT.lzlist(k)) cycle
3836 WHERE (
c_e(field_in(:,:,k)) .AND. field_in(:,:,k) <= this%val_mask(:,:))
3837 field_out(:,:,k) = field_in(:,:,k)
3839 field_out(:,:,k) = rmiss
3843 ELSE IF (this%trans%sub_type ==
'setinvalidto')
THEN 3846 IF (.NOT.lzlist(k)) cycle
3847 WHERE (
c_e(field_in(:,:,k)))
3848 field_out(:,:,k) = field_in(:,:,k)
3850 field_out(:,:,k) = this%val1
3854 ELSE IF (this%trans%sub_type ==
'settoinvalid')
THEN 3855 IF (
c_e(this%val1) .AND.
c_e(this%val2))
THEN 3856 WHERE (
c_e(field_in(:,:,:)) .AND. field_in(:,:,:) > this%val1 &
3857 .AND. field_in(:,:,:) <= this%val2)
3858 field_out(:,:,:) = rmiss
3860 field_out(:,:,:) = field_in(:,:,:)
3862 ELSE IF (
c_e(this%val1))
THEN 3863 WHERE (
c_e(field_in(:,:,:)) .AND. field_in(:,:,:) > this%val1)
3864 field_out(:,:,:) = rmiss
3866 field_out(:,:,:) = field_in(:,:,:)
3868 ELSE IF (
c_e(this%val2))
THEN 3869 WHERE (
c_e(field_in(:,:,:)) .AND. field_in(:,:,:) <= this%val2)
3870 field_out(:,:,:) = rmiss
3872 field_out(:,:,:) = field_in(:,:,:)
3877 ELSE IF (this%trans%trans_type ==
'vertint')
THEN 3879 IF (this%trans%sub_type ==
'linear')
THEN 3881 alloc_coord_3d_in_act = .false.
3882 IF (
ASSOCIATED(this%inter_index_z))
THEN 3885 IF (
c_e(this%inter_index_z(k)))
THEN 3886 z1 =
REAL(this%inter_zp(k)) 3887 z2 =
REAL(1.0D0 - this%inter_zp(k)) 3888 SELECT CASE(vartype)
3893 IF (
c_e(field_in(i,j,this%inter_index_z(k))) .AND. &
3894 c_e(field_in(i,j,this%inter_index_z(k)+1)))
THEN 3895 field_out(i,j,k) = &
3896 interp_var_360(field_in(i,j,this%inter_index_z(k)), &
3897 field_in(i,j,this%inter_index_z(k)+1), z1, z2)
3905 IF (
c_e(field_in(i,j,this%inter_index_z(k))) .AND. &
3906 c_e(field_in(i,j,this%inter_index_z(k)+1)) .AND. &
3907 field_in(i,j,this%inter_index_z(k)) > 0. .AND. &
3908 field_in(i,j,this%inter_index_z(k)+1) > 0.)
THEN 3909 field_out(i,j,k) = exp( &
3910 log(field_in(i,j,this%inter_index_z(k)))*z2 + &
3911 log(field_in(i,j,this%inter_index_z(k)+1))*z1)
3919 IF (
c_e(field_in(i,j,this%inter_index_z(k))) .AND. &
3920 c_e(field_in(i,j,this%inter_index_z(k)+1)))
THEN 3921 field_out(i,j,k) = &
3922 field_in(i,j,this%inter_index_z(k))*z2 + &
3923 field_in(i,j,this%inter_index_z(k)+1)*z1
3935 IF (
ALLOCATED(this%coord_3d_in))
THEN 3936 coord_3d_in_act => this%coord_3d_in
3939 "Using external vertical coordinate for vertint")
3942 IF (
PRESENT(coord_3d_in))
THEN 3945 "Using internal vertical coordinate for vertint")
3947 IF (this%dolog)
THEN 3948 ALLOCATE(coord_3d_in_act(
SIZE(coord_3d_in,1), &
3949 SIZE(coord_3d_in,2),
SIZE(coord_3d_in,3)))
3950 alloc_coord_3d_in_act = .true.
3951 WHERE (
c_e(coord_3d_in) .AND. coord_3d_in > 0.0)
3952 coord_3d_in_act = log(coord_3d_in)
3954 coord_3d_in_act = rmiss
3957 coord_3d_in_act => coord_3d_in
3961 "Missing internal and external vertical coordinate for vertint")
3967 inused =
SIZE(coord_3d_in_act,3)
3968 IF (inused < 2)
RETURN 3972 IF (.NOT.
c_e(this%vcoord_out(k))) cycle
3976 DO kk = 1, max(inused-kkcache-1, kkcache)
3978 kkdown = kkcache - kk + 1
3980 IF (kkdown >= 1)
THEN 3981 IF (this%vcoord_out(k) >= &
3982 min(coord_3d_in_act(i,j,kkdown), coord_3d_in_act(i,j,kkdown+1)) .AND. &
3983 this%vcoord_out(k) < &
3984 max(coord_3d_in_act(i,j,kkdown), coord_3d_in_act(i,j,kkdown+1)))
THEN 3987 kfound = kkcache + this%levshift
3991 IF (kkup < inused)
THEN 3992 IF (this%vcoord_out(k) >= &
3993 min(coord_3d_in_act(i,j,kkup), coord_3d_in_act(i,j,kkup+1)) .AND. &
3994 this%vcoord_out(k) < &
3995 max(coord_3d_in_act(i,j,kkup), coord_3d_in_act(i,j,kkup+1)))
THEN 3998 kfound = kkcache + this%levshift
4005 IF (
c_e(kfound))
THEN 4006 IF (
c_e(field_in(i,j,kfound)) .AND.
c_e(field_in(i,j,kfound+1)))
THEN 4007 z1 =
REAL((this%vcoord_out(k) - coord_3d_in_act(i,j,kfoundin))/ &
4008 (coord_3d_in_act(i,j,kfoundin+1) - coord_3d_in_act(i,j,kfoundin)))
4010 SELECT CASE(vartype)
4013 field_out(i,j,k) = &
4014 interp_var_360(field_in(i,j,kfound), field_in(i,j,kfound+1), z1, z2)
4016 field_out(i,j,k) = exp(log(field_in(i,j,kfound))*z2 + &
4017 log(field_in(i,j,kfound+1))*z1)
4020 field_out(i,j,k) = field_in(i,j,kfound)*z2 + field_in(i,j,kfound+1)*z1
4029 IF (alloc_coord_3d_in_act)
DEALLOCATE(coord_3d_in_act)
4032 ELSE IF (this%trans%sub_type ==
'linearsparse')
THEN 4035 IF (.NOT.
ASSOCIATED(this%vcoord_in) .AND. .NOT.
PRESENT(coord_3d_in))
THEN 4037 "linearsparse interpolation, no input vert coord available")
4041 ALLOCATE(coord_in(innz),val_in(innz),mask_in(innz))
4045 IF (
ASSOCIATED(this%vcoord_in))
THEN 4046 mask_in =
c_e(field_in(i,j,this%levshift+1:this%levshift+this%levused)) &
4047 .AND.
c_e(this%vcoord_in(:))
4049 mask_in =
c_e(field_in(i,j,this%levshift+1:this%levshift+this%levused)) &
4050 .AND.
c_e(coord_3d_in(i,j,:))
4053 IF (vartype == var_press)
THEN 4054 mask_in(:) = mask_in(:) .AND. &
4055 (field_in(i,j,this%levshift+1:this%levshift+this%levused) > 0.0d0)
4057 inused = count(mask_in)
4058 IF (inused > 1)
THEN 4059 IF (
ASSOCIATED(this%vcoord_in))
THEN 4060 coord_in(1:inused) = pack(this%vcoord_in(:), mask=mask_in)
4062 coord_in(1:inused) = pack(coord_3d_in(i,j,:), mask=mask_in)
4064 IF (vartype == var_press)
THEN 4065 val_in(1:inused) = log(pack( &
4066 field_in(i,j,this%levshift+1:this%levshift+this%levused), &
4069 val_in(1:inused) = pack( &
4070 field_in(i,j,this%levshift+1:this%levshift+this%levused), &
4077 DO kk = 1, max(inused-kkcache-1, kkcache)
4079 kkdown = kkcache - kk + 1
4081 IF (kkdown >= 1)
THEN 4082 IF (this%vcoord_out(k) >= &
4083 min(coord_in(kkdown), coord_in(kkdown+1)) .AND. &
4084 this%vcoord_out(k) < &
4085 max(coord_in(kkdown), coord_in(kkdown+1)))
THEN 4092 IF (kkup < inused)
THEN 4093 IF (this%vcoord_out(k) >= &
4094 min(coord_in(kkup), coord_in(kkup+1)) .AND. &
4095 this%vcoord_out(k) < &
4096 max(coord_in(kkup), coord_in(kkup+1)))
THEN 4106 IF (
c_e(kfound))
THEN 4107 z1 =
REAL((this%vcoord_out(k) - coord_in(kfound-1))/ &
4108 (coord_in(kfound) - coord_in(kfound-1)))
4110 IF (vartype == var_dir360)
THEN 4111 field_out(i,j,k) = &
4112 interp_var_360(val_in(kfound-1), val_in(kfound), z1, z2)
4113 ELSE IF (vartype == var_press)
THEN 4114 field_out(i,j,k) = exp(val_in(kfound-1)*z2 + val_in(kfound)*z1)
4116 field_out(i,j,k) = val_in(kfound-1)*z2 + val_in(kfound)*z1
4126 DEALLOCATE(coord_in,val_in)
4131 ELSE IF (this%trans%trans_type ==
'' .OR. this%trans%trans_type ==
'none')
THEN 4133 field_out(:,:,:) = field_in(:,:,:)
4143 FUNCTION interp_var_360(v1, v2, w1, w2)
4144 REAL,
INTENT(in) :: v1, v2, w1, w2
4145 REAL :: interp_var_360
4149 IF (abs(v1 - v2) > 180.)
THEN 4157 interp_var_360 = modulo(lv1*w2 + lv2*w1, 360.)
4159 interp_var_360 = v1*w2 + v2*w1
4162 END FUNCTION interp_var_360
4165 RECURSIVE FUNCTION find_prevailing_direction(v1, l, h, res, mask)
RESULT(prev)
4166 REAL,
INTENT(in) :: v1(:,:)
4167 REAL,
INTENT(in) :: l, h, res
4168 LOGICAL,
INTENT(in),
OPTIONAL :: mask(:,:)
4176 IF ((h - l) <= res)
THEN 4181 IF (
PRESENT(mask))
THEN 4182 nl = count(v1 >= l .AND. v1 < m .AND. mask)
4183 nh = count(v1 >= m .AND. v1 < h .AND. mask)
4185 nl = count(v1 >= l .AND. v1 < m)
4186 nh = count(v1 >= m .AND. v1 < h)
4189 prev = find_prevailing_direction(v1, m, h, res)
4190 ELSE IF (nl > nh)
THEN 4191 prev = find_prevailing_direction(v1, l, m, res)
4192 ELSE IF (nl == 0 .AND. nh == 0)
THEN 4198 END FUNCTION find_prevailing_direction
4201 END SUBROUTINE grid_transform_compute
4209 SUBROUTINE grid_transform_v7d_grid_compute(this, field_in, field_out, var, &
4212 REAL,
INTENT(in) :: field_in(:,:)
4213 REAL,
INTENT(out):: field_out(:,:,:)
4214 TYPE(vol7d_var),
INTENT(in),
OPTIONAL :: var
4215 REAL,
INTENT(in),
OPTIONAL,
TARGET :: coord_3d_in(:,:,:)
4217 real,
allocatable :: field_in_p(:),x_in_p(:),y_in_p(:)
4218 INTEGER :: inn_p, ier, k
4219 INTEGER :: innx, inny, innz, outnx, outny, outnz
4222 call l4f_category_log(this%category,l4f_debug,
"start v7d_grid_transform_compute")
4225 field_out(:,:,:) = rmiss
4227 IF (.NOT.this%valid)
THEN 4229 "refusing to perform a non valid transformation")
4234 innx =
SIZE(field_in,1); inny = 1; innz =
SIZE(field_in,2)
4235 outnx =
SIZE(field_out,1); outny =
SIZE(field_out,2); outnz =
SIZE(field_out,3)
4238 IF (this%trans%trans_type ==
'vertint')
THEN 4240 IF (innz /= this%innz)
THEN 4242 CALL l4f_category_log(this%category,l4f_error,
"inconsistent input shape: "//&
4243 t2c(this%innz)//
" /= "//t2c(innz))
4248 IF (outnz /= this%outnz)
THEN 4250 CALL l4f_category_log(this%category,l4f_error,
"inconsistent output shape: "//&
4251 t2c(this%outnz)//
" /= "//t2c(outnz))
4256 IF (innx /= outnx .OR. inny /= outny)
THEN 4258 CALL l4f_category_log(this%category,l4f_error,
"inconsistent hor. sizes: "//&
4259 t2c(innx)//
","//t2c(inny)//
" /= "//&
4260 t2c(outnx)//
","//t2c(outny))
4267 IF (innx /= this%innx .OR. inny /= this%inny)
THEN 4269 CALL l4f_category_log(this%category,l4f_error,
"inconsistent input shape: "//&
4270 t2c(this%innx)//
","//t2c(this%inny)//
" /= "//&
4271 t2c(innx)//
","//t2c(inny))
4276 IF (outnx /= this%outnx .OR. outny /= this%outny)
THEN 4278 CALL l4f_category_log(this%category,l4f_error,
"inconsistent output shape: "//&
4279 t2c(this%outnx)//
","//t2c(this%outny)//
" /= "//&
4280 t2c(outnx)//
","//t2c(outny))
4285 IF (innz /= outnz)
THEN 4287 CALL l4f_category_log(this%category,l4f_error,
"inconsistent vert. sizes: "//&
4288 t2c(innz)//
" /= "//t2c(outnz))
4297 "start grid_transform_v7d_grid_compute "//trim(this%trans%trans_type)//
':'// &
4298 trim(this%trans%sub_type))
4301 IF (this%trans%trans_type ==
'inter')
THEN 4303 IF (this%trans%sub_type ==
'linear')
THEN 4305 #ifdef HAVE_LIBNGMATH 4307 ALLOCATE(field_in_p(innx*inny), x_in_p(innx*inny), y_in_p(innx*inny))
4309 inn_p = count(
c_e(field_in(:,k)))
4312 "Number of sparse data points: "//t2c(inn_p)//
','//t2c(
SIZE(field_in(:,k))))
4316 field_in_p(1:inn_p) = pack(field_in(:,k),
c_e(field_in(:,k)))
4317 x_in_p(1:inn_p) = pack(this%inter_xp(:,1),
c_e(field_in(:,k)))
4318 y_in_p(1:inn_p) = pack(this%inter_yp(:,1),
c_e(field_in(:,k)))
4320 IF (.NOT.this%trans%extrap)
THEN 4321 CALL nnseti(
'ext', 0)
4322 CALL nnsetr(
'nul', rmiss)
4325 CALL natgrids(inn_p, x_in_p, y_in_p, field_in_p, &
4326 this%outnx, this%outny,
REAL(this%inter_x(:,1)), &
4327 REAL(this%inter_y(1,:)), field_out(1,1,k), ier)
4331 "Error code from NCAR natgrids: "//t2c(ier))
4338 "insufficient data in gridded region to triangulate")
4342 DEALLOCATE(field_in_p, x_in_p, y_in_p)
4346 "libsim compiled without NATGRIDD (ngmath ncarg library)")
4353 ELSE IF (this%trans%trans_type ==
'boxinter' .OR. &
4354 this%trans%trans_type ==
'polyinter' .OR. &
4355 this%trans%trans_type ==
'vertint' .OR. &
4356 this%trans%trans_type ==
'metamorphosis')
THEN 4359 reshape(field_in, (/
SIZE(field_in,1), 1,
SIZE(field_in,2)/)), field_out, var, &
4364 END SUBROUTINE grid_transform_v7d_grid_compute
4379 ELEMENTAL FUNCTION hbilin (z1,z2,z3,z4,x1,y1,x3,y3,xp,yp)
RESULT(zp)
4380 REAL,
INTENT(in) :: z1,z2,z3,z4
4381 DOUBLE PRECISION,
INTENT(in):: x1,y1
4382 DOUBLE PRECISION,
INTENT(in):: x3,y3
4383 DOUBLE PRECISION,
INTENT(in):: xp,yp
4390 p2 =
REAL((yp-y1)/(y3-y1))
4391 p1 =
REAL((xp-x1)/(x3-x1))
4396 zp = (z6-z5)*(p1)+z5
4402 FUNCTION shapiro (z,zp)
RESULT(zs)
4405 REAL,
INTENT(in) :: z(:)
4406 REAL,
INTENT(in) :: zp
4412 zs = zp - 0.5* ( n*zp - sum(z,
c_e(z)) )/n
4417 END FUNCTION shapiro
4421 SUBROUTINE basic_find_index(this, near, nx, ny, xmin, xmax, ymin, ymax, &
4422 lon, lat, extrap, index_x, index_y)
4423 TYPE(griddim_def),
INTENT(in) :: this
4424 LOGICAL,
INTENT(in) :: near
4425 INTEGER,
INTENT(in) :: nx,ny
4426 DOUBLE PRECISION,
INTENT(in) :: xmin, xmax, ymin, ymax
4427 DOUBLE PRECISION,
INTENT(in) :: lon(:,:),lat(:,:)
4428 LOGICAL,
INTENT(in) :: extrap
4429 INTEGER,
INTENT(out) :: index_x(:,:),index_y(:,:)
4432 DOUBLE PRECISION :: x(SIZE(lon,1),SIZE(lon,2)),y(SIZE(lon,1),SIZE(lon,2))
4435 CALL proj(this,lon,lat,x,y)
4436 index_x = nint((x-xmin)/((xmax-xmin)/dble(nx-1)))+1
4437 index_y = nint((y-ymin)/((ymax-ymin)/dble(ny-1)))+1
4441 CALL proj(this,lon,lat,x,y)
4442 index_x = floor((x-xmin)/((xmax-xmin)/dble(nx-1)))+1
4443 index_y = floor((y-ymin)/((ymax-ymin)/dble(ny-1)))+1
4449 index_x = max(index_x, 1)
4450 index_y = max(index_y, 1)
4451 index_x = min(index_x, lnx)
4452 index_y = min(index_y, lny)
4454 WHERE(index_x < 1 .OR. index_x > lnx .OR. index_y < 1 .OR. index_y > lny)
4460 END SUBROUTINE basic_find_index
Compute the average of the random variable provided, taking into account missing data.
Compute forward coordinate transformation from geographical system to projected system.
Compute the distance in m between two points.
Module for quickly interpreting the OPTIONAL parameters passed to a subprogram.
Compute a set of percentiles for a random variable.
Module for describing geographically referenced regular grids.
Represent data in a pretty string.
This module defines objects describing georeferenced sparse points possibly with topology and project...
Compute the standard deviation of the random variable provided, taking into account missing data...
Determine whether a point lies inside a polygon or a rectangle.
Generic subroutine for checking OPTIONAL parameters.
Compute backward coordinate transformation from projected system to geographical system.
Classe per la gestione di un volume completo di dati osservati.
Methods for returning the value of object members.
This module defines usefull general purpose function and subroutine.
Module for defining the extension and coordinates of a rectangular georeferenced grid.
Module for basic statistical computations taking into account missing data.
classe per la gestione del logging
Method for setting the contents of the object.
Emit log message for a category with specific priority.