libsim  Versione8.0.0
volgrid6d_class.F90
1 ! Copyright (C) 2010 ARPA-SIM <urpsim@smr.arpa.emr.it>
2 ! authors:
3 ! Davide Cesari <dcesari@arpa.emr.it>
4 ! Paolo Patruno <ppatruno@arpa.emr.it>
5 
6 ! This program is free software; you can redistribute it and/or
7 ! modify it under the terms of the GNU General Public License as
8 ! published by the Free Software Foundation; either version 2 of
9 ! the License, or (at your option) any later version.
10 
11 ! This program is distributed in the hope that it will be useful,
12 ! but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ! GNU General Public License for more details.
15 
16 ! You should have received a copy of the GNU General Public License
17 ! along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "config.h"
19 
31 
52 MODULE volgrid6d_class
55 USE vol7d_class
57 USE geo_proj_class
58 USE grid_class
62 USE log4fortran
64 USE grid_id_class
67 !USE file_utilities
68 #ifdef HAVE_DBALLE
70 #endif
71 IMPLICIT NONE
72 
73 character (len=255),parameter:: subcategory="volgrid6d_class"
74 
76 type volgrid6d
77  type(griddim_def) :: griddim
78  TYPE(datetime),pointer :: time(:)
79  TYPE(vol7d_timerange),pointer :: timerange(:)
80  TYPE(vol7d_level),pointer :: level(:)
81  TYPE(volgrid6d_var),pointer :: var(:)
82  TYPE(grid_id),POINTER :: gaid(:,:,:,:)
83  REAL,POINTER :: voldati(:,:,:,:,:,:)
84  INTEGER :: time_definition
85  TYPE(l4f_handle) :: category
86 end type volgrid6d
87 
89 INTERFACE init
90  MODULE PROCEDURE volgrid6d_init
91 END INTERFACE
92 
95 INTERFACE delete
96  MODULE PROCEDURE volgrid6d_delete, volgrid6dv_delete
97 END INTERFACE
98 
101 INTERFACE import
102  MODULE PROCEDURE volgrid6d_read_from_file
103  MODULE PROCEDURE import_from_gridinfo, import_from_gridinfovv, &
104  volgrid6d_import_from_file
105 END INTERFACE
106 
109 INTERFACE export
110  MODULE PROCEDURE volgrid6d_write_on_file
111  MODULE PROCEDURE export_to_gridinfo, export_to_gridinfov, export_to_gridinfovv,&
112  volgrid6d_export_to_file
113 END INTERFACE
114 
115 ! methods for computing transformations through an initialised
116 ! grid_transform object, probably too low level to be interfaced
117 INTERFACE compute
118  MODULE PROCEDURE volgrid6d_transform_compute, volgrid6d_v7d_transform_compute,&
119  v7d_volgrid6d_transform_compute, v7d_v7d_transform_compute
120 END INTERFACE
121 
124 INTERFACE transform
125  MODULE PROCEDURE volgrid6d_transform, volgrid6dv_transform,&
126  volgrid6d_v7d_transform, volgrid6dv_v7d_transform, v7d_volgrid6d_transform, &
127  v7d_v7d_transform
128 END INTERFACE
129 
130 INTERFACE wind_rot
131  MODULE PROCEDURE vg6d_wind_rot
132 END INTERFACE
133 
134 INTERFACE wind_unrot
135  MODULE PROCEDURE vg6d_wind_unrot
136 END INTERFACE
137 
140 INTERFACE display
141  MODULE PROCEDURE display_volgrid6d,display_volgrid6dv
142 END INTERFACE
143 
155 INTERFACE rounding
156  MODULE PROCEDURE vg6d_rounding, vg6dv_rounding
157 END INTERFACE
158 
159 private
160 
161 PUBLIC volgrid6d,init,delete,export,import,compute,transform, &
162  wind_rot,wind_unrot,vg6d_c2a,display,volgrid6d_alloc,volgrid6d_alloc_vol, &
163  volgrid_get_vol_2d, volgrid_set_vol_2d, volgrid_get_vol_3d, volgrid_set_vol_3d
164 PUBLIC rounding, vg6d_reduce
165 
166 CONTAINS
167 
168 
173 SUBROUTINE volgrid6d_init(this, griddim, time_definition, categoryappend)
174 TYPE(volgrid6d) :: this
175 TYPE(griddim_def),OPTIONAL :: griddim
176 INTEGER,INTENT(IN),OPTIONAL :: time_definition
177 CHARACTER(len=*),INTENT(in),OPTIONAL :: categoryappend
178 
179 character(len=512) :: a_name
180 
181 if (present(categoryappend))then
182  call l4f_launcher(a_name,a_name_append=trim(subcategory)//"."//trim(categoryappend))
183 else
184  call l4f_launcher(a_name,a_name_append=trim(subcategory))
185 endif
186 this%category=l4f_category_get_handle(a_name)
187 
188 #ifdef DEBUG
189 call l4f_category_log(this%category,l4f_debug,"init")
190 #endif
191 
192 call init(this%griddim)
193 
194 if (present(griddim))then
195  call copy (griddim,this%griddim)
196 end if
197 
198 if(present(time_definition)) then
199  this%time_definition = time_definition
200 else
201  this%time_definition = 0 !default to reference time
202 end if
203 
204 nullify (this%time,this%timerange,this%level,this%var)
205 nullify (this%gaid,this%voldati)
206 
207 END SUBROUTINE volgrid6d_init
208 
209 
220 SUBROUTINE volgrid6d_alloc(this, dim, ntime, nlevel, ntimerange, nvar, ini)
221 TYPE(volgrid6d),INTENT(inout) :: this
222 TYPE(grid_dim),INTENT(in),OPTIONAL :: dim
223 INTEGER,INTENT(in),OPTIONAL :: ntime
224 INTEGER,INTENT(in),OPTIONAL :: nlevel
225 INTEGER,INTENT(in),OPTIONAL :: ntimerange
226 INTEGER,INTENT(in),OPTIONAL :: nvar
227 LOGICAL,INTENT(in),OPTIONAL :: ini
228 
229 INTEGER :: i, stallo
230 LOGICAL :: linit
231 
232 #ifdef DEBUG
233 call l4f_category_log(this%category,l4f_debug,"alloc")
234 #endif
235 
236 IF (PRESENT(ini)) THEN
237  linit = ini
238 ELSE
239  linit = .false.
240 ENDIF
241 
242 
243 if (present(dim)) call copy (dim,this%griddim%dim)
244 
245 
246 IF (PRESENT(ntime)) THEN
247  IF (ntime >= 0) THEN
248  IF (ASSOCIATED(this%time)) DEALLOCATE(this%time)
249 #ifdef DEBUG
250  call l4f_category_log(this%category,l4f_debug,"alloc ntime "//to_char(ntime))
251 #endif
252  ALLOCATE(this%time(ntime),stat=stallo)
253  if (stallo /=0)then
254  call l4f_category_log(this%category,l4f_fatal,"allocating memory")
255  CALL raise_fatal_error()
256  end if
257  IF (linit) THEN
258  DO i = 1, ntime
259  this%time(i) = datetime_miss
260 ! CALL init(this%time(i)) ! senza argomento inizializza a zero non missing
261  ! baco di datetime?
262  ENDDO
263  ENDIF
264  ENDIF
265 ENDIF
266 IF (PRESENT(nlevel)) THEN
267  IF (nlevel >= 0) THEN
268  IF (ASSOCIATED(this%level)) DEALLOCATE(this%level)
269 #ifdef DEBUG
270  call l4f_category_log(this%category,l4f_debug,"alloc nlevel "//to_char(nlevel))
271 #endif
272  ALLOCATE(this%level(nlevel),stat=stallo)
273  if (stallo /=0)then
274  call l4f_category_log(this%category,l4f_fatal,"allocating memory")
275  CALL raise_fatal_error()
276  end if
277  IF (linit) THEN
278  DO i = 1, nlevel
279  CALL init(this%level(i))
280  ENDDO
281  ENDIF
282  ENDIF
283 ENDIF
284 IF (PRESENT(ntimerange)) THEN
285  IF (ntimerange >= 0) THEN
286  IF (ASSOCIATED(this%timerange)) DEALLOCATE(this%timerange)
287 #ifdef DEBUG
288  call l4f_category_log(this%category,l4f_debug,"alloc ntimerange "//to_char(ntimerange))
289 #endif
290  ALLOCATE(this%timerange(ntimerange),stat=stallo)
291  if (stallo /=0)then
292  call l4f_category_log(this%category,l4f_fatal,"allocating memory")
293  CALL raise_fatal_error()
294  end if
295  IF (linit) THEN
296  DO i = 1, ntimerange
297  CALL init(this%timerange(i))
298  ENDDO
299  ENDIF
300  ENDIF
301 ENDIF
302 IF (PRESENT(nvar)) THEN
303  IF (nvar >= 0) THEN
304  IF (ASSOCIATED(this%var)) DEALLOCATE(this%var)
305 #ifdef DEBUG
306  call l4f_category_log(this%category,l4f_debug,"alloc nvar "//to_char(nvar))
307 #endif
308  ALLOCATE(this%var(nvar),stat=stallo)
309  if (stallo /=0)then
310  call l4f_category_log(this%category,l4f_fatal,"allocating memory")
311  CALL raise_fatal_error()
312  end if
313  IF (linit) THEN
314  DO i = 1, nvar
315  CALL init(this%var(i))
316  ENDDO
317  ENDIF
318  ENDIF
319 ENDIF
320 
321 end SUBROUTINE volgrid6d_alloc
323 
332 SUBROUTINE volgrid6d_alloc_vol(this, ini, inivol, decode)
333 TYPE(volgrid6d),INTENT(inout) :: this
334 LOGICAL,INTENT(in),OPTIONAL :: ini
335 LOGICAL,INTENT(in),OPTIONAL :: inivol
336 LOGICAL,INTENT(in),OPTIONAL :: decode
337 
338 INTEGER :: stallo
339 LOGICAL :: linivol
340 
341 #ifdef DEBUG
342 call l4f_category_log(this%category,l4f_debug,"start alloc_vol")
343 #endif
344 
345 IF (PRESENT(inivol)) THEN ! opposite condition, cannot use optio_log
346  linivol = inivol
347 ELSE
348  linivol = .true.
349 ENDIF
350 
351 IF (this%griddim%dim%nx > 0 .AND. this%griddim%dim%ny > 0) THEN
352 ! allocate dimension descriptors to a minimal size for having a
353 ! non-null volume
354  IF (.NOT. ASSOCIATED(this%var)) CALL volgrid6d_alloc(this, nvar=1, ini=ini)
355  IF (.NOT. ASSOCIATED(this%time)) CALL volgrid6d_alloc(this, ntime=1, ini=ini)
356  IF (.NOT. ASSOCIATED(this%level)) CALL volgrid6d_alloc(this, nlevel=1, ini=ini)
357  IF (.NOT. ASSOCIATED(this%timerange)) CALL volgrid6d_alloc(this, ntimerange=1, ini=ini)
358 
359  IF (optio_log(decode)) THEN
360  IF (.NOT.ASSOCIATED(this%voldati)) THEN
361 #ifdef DEBUG
362  CALL l4f_category_log(this%category,l4f_debug,"alloc voldati volume")
363 #endif
364 
365  ALLOCATE(this%voldati(this%griddim%dim%nx,this%griddim%dim%ny,&
366  SIZE(this%level), SIZE(this%time), &
367  SIZE(this%timerange), SIZE(this%var)),stat=stallo)
368  IF (stallo /= 0)THEN
369  CALL l4f_category_log(this%category,l4f_fatal,"allocating memory")
370  CALL raise_fatal_error()
371  ENDIF
372 
373 ! this is not really needed if we can check other flags for a full
374 ! field missing values
375  IF (linivol) this%voldati = rmiss
376  this%voldati = rmiss
377  ENDIF
378  ENDIF
379 
380  IF (.NOT.ASSOCIATED(this%gaid)) THEN
381 #ifdef DEBUG
382  CALL l4f_category_log(this%category,l4f_debug,"alloc gaid volume")
383 #endif
384  ALLOCATE(this%gaid(SIZE(this%level), SIZE(this%time), &
385  SIZE(this%timerange), SIZE(this%var)),stat=stallo)
386  IF (stallo /= 0)THEN
387  CALL l4f_category_log(this%category,l4f_fatal,"allocating memory")
388  CALL raise_fatal_error()
389  ENDIF
390 
391  IF (linivol) THEN
392 !!$ DO i=1 ,SIZE(this%gaid,1)
393 !!$ DO ii=1 ,SIZE(this%gaid,2)
394 !!$ DO iii=1 ,SIZE(this%gaid,3)
395 !!$ DO iiii=1 ,SIZE(this%gaid,4)
396 !!$ this%gaid(i,ii,iii,iiii) = grid_id_new() ! optimize?
397 !!$ ENDDO
398 !!$ ENDDO
399 !!$ ENDDO
400 !!$ ENDDO
401 
402  this%gaid = grid_id_new()
403  ENDIF
404  ENDIF
405 
406 ELSE
407  CALL l4f_category_log(this%category,l4f_fatal,'volgrid6d_alloc_vol: &
408  &trying to allocate a volume with an invalid or unspecified horizontal grid')
409  CALL raise_fatal_error()
410 ENDIF
411 
412 END SUBROUTINE volgrid6d_alloc_vol
413 
414 
428 SUBROUTINE volgrid_get_vol_2d(this, ilevel, itime, itimerange, ivar, voldati)
429 TYPE(volgrid6d),INTENT(in) :: this
430 INTEGER,INTENT(in) :: ilevel
431 INTEGER,INTENT(in) :: itime
432 INTEGER,INTENT(in) :: itimerange
433 INTEGER,INTENT(in) :: ivar
434 REAL,POINTER :: voldati(:,:)
435 
436 IF (ASSOCIATED(this%voldati)) THEN
437  voldati => this%voldati(:,:,ilevel,itime,itimerange,ivar)
438  RETURN
439 ELSE
440  IF (.NOT.ASSOCIATED(voldati)) THEN
441  ALLOCATE(voldati(this%griddim%dim%nx,this%griddim%dim%ny))
442  ENDIF
443  CALL grid_id_decode_data(this%gaid(ilevel,itime,itimerange,ivar), voldati)
444 ENDIF
445 
446 END SUBROUTINE volgrid_get_vol_2d
447 
448 
462 SUBROUTINE volgrid_get_vol_3d(this, itime, itimerange, ivar, voldati, zlist)
463 TYPE(volgrid6d),INTENT(in) :: this
464 INTEGER,INTENT(in) :: itime
465 INTEGER,INTENT(in) :: itimerange
466 INTEGER,INTENT(in) :: ivar
467 REAL,POINTER :: voldati(:,:,:)
468 LOGICAL,OPTIONAL,INTENT(out),ALLOCATABLE :: zlist(:)
469 
470 INTEGER :: ilevel
471 LOGICAL :: done
472 
473 IF (ASSOCIATED(this%voldati)) THEN
474  voldati => this%voldati(:,:,:,itime,itimerange,ivar)
475  IF (PRESENT(zlist)) zlist(:) = c_e(this%gaid(:,itime,itimerange,ivar))
476  RETURN
477 ELSE
478  IF (.NOT.ASSOCIATED(voldati)) THEN
479  ALLOCATE(voldati(this%griddim%dim%nx,this%griddim%dim%ny,SIZE(this%level)))
480  ENDIF
481  IF (PRESENT(zlist)) THEN
482  ALLOCATE(zlist(SIZE(this%level)))
483  ENDIF
484 !$OMP PARALLEL DEFAULT(SHARED)
485 !$OMP MASTER
486  DO ilevel = 1, SIZE(this%level)
487 !$OMP TASK FIRSTPRIVATE(ilevel),PRIVATE(done)
488  CALL grid_id_decode_data(this%gaid(ilevel,itime,itimerange,ivar), &
489  voldati(:,:,ilevel),done)
490  IF (PRESENT(zlist)) zlist(ilevel) = done
491 !$OMP END TASK
492  ENDDO
493 !$OMP END MASTER
494 !$OMP END PARALLEL
495 ENDIF
496 
497 END SUBROUTINE volgrid_get_vol_3d
498 
499 
511 SUBROUTINE volgrid_set_vol_2d(this, ilevel, itime, itimerange, ivar, voldati)
512 TYPE(volgrid6d),INTENT(inout) :: this
513 INTEGER,INTENT(in) :: ilevel
514 INTEGER,INTENT(in) :: itime
515 INTEGER,INTENT(in) :: itimerange
516 INTEGER,INTENT(in) :: ivar
517 REAL,INTENT(in) :: voldati(:,:)
518 
519 IF (ASSOCIATED(this%voldati)) THEN
520  RETURN
521 ELSE
522  CALL grid_id_encode_data(this%gaid(ilevel,itime,itimerange,ivar), voldati)
523 ENDIF
524 
525 END SUBROUTINE volgrid_set_vol_2d
526 
527 
539 SUBROUTINE volgrid_set_vol_3d(this, itime, itimerange, ivar, voldati)
540 TYPE(volgrid6d),INTENT(inout) :: this
541 INTEGER,INTENT(in) :: itime
542 INTEGER,INTENT(in) :: itimerange
543 INTEGER,INTENT(in) :: ivar
544 REAL,INTENT(in) :: voldati(:,:,:)
545 
546 INTEGER :: ilevel
547 
548 IF (ASSOCIATED(this%voldati)) THEN
549  RETURN
550 ELSE
551 !$OMP PARALLEL DEFAULT(SHARED)
552 !$OMP MASTER
553  DO ilevel = 1, SIZE(this%level)
554 !$OMP TASK FIRSTPRIVATE(ilevel)
555  CALL grid_id_encode_data(this%gaid(ilevel,itime,itimerange,ivar), &
556  voldati(:,:,ilevel))
557 !$OMP END TASK
558  ENDDO
559 !$OMP END MASTER
560 !$OMP END PARALLEL
561 ENDIF
562 
563 END SUBROUTINE volgrid_set_vol_3d
564 
565 
569 SUBROUTINE volgrid6d_delete(this)
570 TYPE(volgrid6d),INTENT(inout) :: this
571 
572 INTEGER :: i, ii, iii, iiii
573 
574 #ifdef DEBUG
575 call l4f_category_log(this%category,l4f_debug,"delete")
576 #endif
577 
578 if (associated(this%gaid))then
579 
580  DO i=1 ,SIZE(this%gaid,1)
581  DO ii=1 ,SIZE(this%gaid,2)
582  DO iii=1 ,SIZE(this%gaid,3)
583  DO iiii=1 ,SIZE(this%gaid,4)
584  CALL delete(this%gaid(i,ii,iii,iiii))
585  ENDDO
586  ENDDO
587  ENDDO
588  ENDDO
589  DEALLOCATE(this%gaid)
590 
591 end if
592 
593 call delete(this%griddim)
594 
595 ! call delete(this%time)
596 ! call delete(this%timerange)
597 ! call delete(this%level)
598 ! call delete(this%var)
599 
600 if (associated( this%time )) deallocate(this%time)
601 if (associated( this%timerange )) deallocate(this%timerange)
602 if (associated( this%level )) deallocate(this%level)
603 if (associated( this%var )) deallocate(this%var)
604 
605 if (associated(this%voldati))deallocate(this%voldati)
606 
607 
608  !chiudo il logger
609 call l4f_category_delete(this%category)
610 
611 END SUBROUTINE volgrid6d_delete
612 
613 
623 subroutine volgrid6d_write_on_file (this,unit,description,filename,filename_auto)
624 
625 TYPE(volgrid6d),INTENT(IN) :: this
626 integer,optional,intent(inout) :: unit
627 character(len=*),intent(in),optional :: filename
628 character(len=*),intent(out),optional :: filename_auto
629 character(len=*),INTENT(IN),optional :: description
630 
631 integer :: lunit
632 character(len=254) :: ldescription,arg,lfilename
633 integer :: ntime, ntimerange, nlevel, nvar
634 integer :: tarray(8)
635 logical :: opened,exist
636 
637 #ifdef DEBUG
638 call l4f_category_log(this%category,l4f_debug,"write on file")
639 #endif
640 
641 ntime=0
642 ntimerange=0
643 nlevel=0
644 nvar=0
645 
646 !call idate(im,id,iy)
647 call date_and_time(values=tarray)
648 call getarg(0,arg)
649 
650 if (present(description))then
651  ldescription=description
652 else
653  ldescription="Volgrid6d generated by: "//trim(arg)
654 end if
655 
656 if (.not. present(unit))then
657  lunit=getunit()
658 else
659  if (unit==0)then
660  lunit=getunit()
661  unit=lunit
662  else
663  lunit=unit
664  end if
665 end if
666 
667 lfilename=trim(arg)//".vg6d"
668 if (index(arg,'/',back=.true.) > 0) lfilename=lfilename(index(arg,'/',back=.true.)+1 : )
669 
670 if (present(filename))then
671  if (filename /= "")then
672  lfilename=filename
673  end if
674 end if
675 
676 if (present(filename_auto))filename_auto=lfilename
677 
678 
679 inquire(unit=lunit,opened=opened)
680 if (.not. opened) then
681  inquire(file=lfilename,exist=exist)
682  if (exist) CALL raise_error('file exist; cannot open new file')
683  if (.not.exist) open (unit=lunit,file=lfilename,form="UNFORMATTED")
684  !print *, "opened: ",lfilename
685 end if
686 
687 if (associated(this%time)) ntime=size(this%time)
688 if (associated(this%timerange)) ntimerange=size(this%timerange)
689 if (associated(this%level)) nlevel=size(this%level)
690 if (associated(this%var)) nvar=size(this%var)
691 
692 
693 write(unit=lunit)ldescription
694 write(unit=lunit)tarray
695 
696 call write_unit( this%griddim,lunit)
697 write(unit=lunit) ntime, ntimerange, nlevel, nvar
698 
699 !! prime 4 dimensioni
700 if (associated(this%time)) call write_unit(this%time, lunit)
701 if (associated(this%level)) write(unit=lunit)this%level
702 if (associated(this%timerange)) write(unit=lunit)this%timerange
703 if (associated(this%var)) write(unit=lunit)this%var
704 
705 
706 !! Volumi di valori dati
707 
708 if (associated(this%voldati)) write(unit=lunit)this%voldati
709 
710 if (.not. present(unit)) close(unit=lunit)
711 
712 end subroutine volgrid6d_write_on_file
713 
714 
721 subroutine volgrid6d_read_from_file (this,unit,filename,description,tarray,filename_auto)
722 
723 TYPE(volgrid6d),INTENT(OUT) :: this
724 integer,intent(inout),optional :: unit
725 character(len=*),INTENT(in),optional :: filename
726 character(len=*),intent(out),optional :: filename_auto
727 character(len=*),INTENT(out),optional :: description
728 integer,intent(out),optional :: tarray(8)
729 
730 integer :: ntime, ntimerange, nlevel, nvar
731 
732 character(len=254) :: ldescription,lfilename,arg
733 integer :: ltarray(8),lunit
734 logical :: opened,exist
735 
736 #ifdef DEBUG
737 call l4f_category_log(this%category,l4f_debug,"read from file")
738 #endif
739 
740 call getarg(0,arg)
741 
742 if (.not. present(unit))then
743  lunit=getunit()
744 else
745  if (unit==0)then
746  lunit=getunit()
747  unit=lunit
748  else
749  lunit=unit
750  end if
751 end if
752 
753 lfilename=trim(arg)//".vg6d"
754 if (index(arg,'/',back=.true.) > 0) lfilename=lfilename(index(arg,'/',back=.true.)+1 : )
755 
756 if (present(filename))then
757  if (filename /= "")then
758  lfilename=filename
759  end if
760 end if
761 
762 if (present(filename_auto))filename_auto=lfilename
763 
764 
765 inquire(unit=lunit,opened=opened)
766 if (.not. opened) then
767  inquire(file=lfilename,exist=exist)
768  IF (.NOT. exist) CALL raise_fatal_error('file '//trim(lfilename)//' does not exist, cannot open')
769  open (unit=lunit,file=lfilename,form="UNFORMATTED")
770 end if
771 
772 read(unit=lunit)ldescription
773 read(unit=lunit)ltarray
774 
775 call l4f_log(l4f_info,"Info: reading volgrid6d from file: "//trim(lfilename))
776 call l4f_log(l4f_info,"Info: description: "//trim(ldescription))
777 !call l4f_log("Info: written on ",ltarray)
778 
779 if (present(description))description=ldescription
780 if (present(tarray))tarray=ltarray
781 
782 
783 call read_unit( this%griddim,lunit)
784 read(unit=lunit) ntime, ntimerange, nlevel, nvar
785 
786 
787 call volgrid6d_alloc (this, &
788  ntime=ntime, ntimerange=ntimerange, nlevel=nlevel, nvar=nvar)
789 
790 call volgrid6d_alloc_vol (this)
791 
792 if (associated(this%time)) call read_unit(this%time, lunit)
793 if (associated(this%level)) read(unit=lunit)this%level
794 if (associated(this%timerange)) read(unit=lunit)this%timerange
795 if (associated(this%var)) read(unit=lunit)this%var
796 
797 
798 !! Volumi di valori
799 
800 if (associated(this%voldati)) read(unit=lunit)this%voldati
801 
802 if (.not. present(unit)) close(unit=lunit)
803 
804 end subroutine volgrid6d_read_from_file
805 
806 
826 SUBROUTINE import_from_gridinfo(this, gridinfo, force, dup_mode, clone, &
827  isanavar)
828 TYPE(volgrid6d),INTENT(inout) :: this
829 TYPE(gridinfo_def),INTENT(in) :: gridinfo
830 LOGICAL,INTENT(in),OPTIONAL :: force
831 INTEGER,INTENT(in),OPTIONAL :: dup_mode
832 LOGICAL , INTENT(in),OPTIONAL :: clone
833 LOGICAL,INTENT(IN),OPTIONAL :: isanavar
834 
835 CHARACTER(len=255) :: type
836 INTEGER :: itime0, itimerange0, itime1, itimerange1, itime, itimerange, &
837  ilevel, ivar, ldup_mode
838 LOGICAL :: dup
839 TYPE(datetime) :: correctedtime
840 TYPE(vol7d_timerange) :: correctedtimerange
841 REAL,ALLOCATABLE :: tmpgrid(:,:)
842 
843 IF (PRESENT(dup_mode)) THEN
844  ldup_mode = dup_mode
845 ELSE
846  ldup_mode = 0
847 ENDIF
848 
849 call get_val(this%griddim,proj_type=type)
850 
851 #ifdef DEBUG
852 call l4f_category_log(this%category,l4f_debug,"import_from_gridinfo: "//trim(type))
853 #endif
854 
855 if (.not. c_e(type))then
856  call copy(gridinfo%griddim, this%griddim)
857 ! ho gia` fatto init, altrimenti non potrei fare la get_val(this%griddim)
858 ! per cui meglio non ripetere
859 ! call init(this,gridinfo%griddim,categoryappend)
860  CALL volgrid6d_alloc_vol(this, ini=.true.) ! decode?
861 
862 else if (.not. (this%griddim == gridinfo%griddim ))then
863 
864  CALL l4f_category_log(this%category,l4f_error, &
865  "volgrid and gridinfo grid type or size are different, gridinfo rejected")
866  CALL raise_error()
867  RETURN
868 
869 end if
870 
871 ! Cerco gli indici del campo da inserire, se non trovo metto nel primo missing
872 ilevel = index(this%level, gridinfo%level)
873 IF (ilevel == 0 .AND. optio_log(force)) THEN
874  ilevel = index(this%level, vol7d_level_miss)
875  IF (ilevel /= 0) this%level(ilevel) = gridinfo%level
876 ENDIF
877 
878 IF (ilevel == 0) THEN
879  CALL l4f_category_log(this%category,l4f_error, &
880  "volgrid6d: level not valid for volume, gridinfo rejected")
881  CALL raise_error()
882  RETURN
883 ENDIF
884 
885 IF (optio_log(isanavar)) THEN ! assign to all times and timeranges
886  itime0 = 1
887  itime1 = SIZE(this%time)
888  itimerange0 = 1
889  itimerange1 = SIZE(this%timerange)
890 ELSE ! usual case
891  correctedtime = gridinfo%time
892  IF (this%time_definition == 1 .OR. this%time_definition == 2) correctedtime = correctedtime + &
893  timedelta_new(sec=gridinfo%timerange%p1)
894  itime0 = index(this%time, correctedtime)
895  IF (itime0 == 0 .AND. optio_log(force)) THEN
896  itime0 = index(this%time, datetime_miss)
897  IF (itime0 /= 0) this%time(itime0) = correctedtime
898  ENDIF
899  IF (itime0 == 0) THEN
900  CALL l4f_category_log(this%category,l4f_error, &
901  "volgrid6d: time not valid for volume, gridinfo rejected")
902  CALL raise_error()
903  RETURN
904  ENDIF
905  itime1 = itime0
906 
907  correctedtimerange = gridinfo%timerange
908  IF (this%time_definition == 2) correctedtimerange%p1 = 0
909  itimerange0 = index(this%timerange, correctedtimerange)
910  IF (itimerange0 == 0 .AND. optio_log(force)) THEN
911  itimerange0 = index(this%timerange, vol7d_timerange_miss)
912  IF (itimerange0 /= 0) this%timerange(itimerange0) = gridinfo%timerange
913  ENDIF
914  IF (itimerange0 == 0) THEN
915  CALL l4f_category_log(this%category,l4f_error, &
916  "volgrid6d: timerange not valid for volume, gridinfo rejected")
917  CALL raise_error()
918  RETURN
919  ENDIF
920  itimerange1 = itimerange0
921 ENDIF
922 
923 ivar = index(this%var, gridinfo%var)
924 IF (ivar == 0 .AND. optio_log(force)) THEN
925  ivar = index(this%var, volgrid6d_var_miss)
926  IF (ivar /= 0) this%var(ivar) = gridinfo%var
927 ENDIF
928 IF (ivar == 0) THEN
929  CALL l4f_category_log(this%category,l4f_error, &
930  "volgrid6d: var not valid for volume, gridinfo rejected")
931  CALL raise_error()
932  RETURN
933 ENDIF
934 
935 DO itimerange = itimerange0, itimerange1
936  DO itime = itime0, itime1
937  IF (ASSOCIATED(this%gaid)) THEN
938  dup = .false.
939  IF (c_e(this%gaid(ilevel,itime,itimerange,ivar))) THEN
940  dup = .true.
941  CALL l4f_category_log(this%category,l4f_warn,"gaid exist: grib duplicated")
942 ! avoid memory leaks
943  IF (optio_log(clone)) CALL delete(this%gaid(ilevel,itime,itimerange,ivar))
944  ENDIF
945 
946  IF (optio_log(clone)) THEN
947  CALL copy(gridinfo%gaid, this%gaid(ilevel,itime,itimerange,ivar))
948 #ifdef DEBUG
949  CALL l4f_category_log(this%category,l4f_debug,"cloning to a new gaid")
950 #endif
951  ELSE
952  this%gaid(ilevel,itime,itimerange,ivar) = gridinfo%gaid
953  ENDIF
954 
955  IF (ASSOCIATED(this%voldati))THEN
956  IF (.NOT.dup .OR. ldup_mode == 0) THEN
957  this%voldati(:,:,ilevel,itime,itimerange,ivar) = decode_gridinfo(gridinfo)
958  ELSE IF (ldup_mode == 1) THEN
959  tmpgrid = decode_gridinfo(gridinfo) ! f2003 automatic allocation
960  WHERE(c_e(tmpgrid))
961  this%voldati(:,:,ilevel,itime,itimerange,ivar) = tmpgrid(:,:)
962  END WHERE
963  ELSE IF (ldup_mode == 2) THEN
964  WHERE(.NOT.c_e(this%voldati(:,:,ilevel,itime,itimerange,ivar)))
965  this%voldati(:,:,ilevel,itime,itimerange,ivar) = decode_gridinfo(gridinfo)
966  END WHERE
967  ENDIF
968  ENDIF
969 
970  ELSE
971  CALL l4f_category_log(this%category,l4f_error, &
972  "gaid not allocated, you probably need to call volgrid6d_alloc_vol first")
973  CALL raise_error()
974  RETURN
975  ENDIF
976  ENDDO
977 ENDDO
978 
979 
980 END SUBROUTINE import_from_gridinfo
981 
982 
987 SUBROUTINE export_to_gridinfo(this, gridinfo, itime, itimerange, ilevel, ivar, &
988  gaid_template, clone)
989 TYPE(volgrid6d),INTENT(in) :: this
990 TYPE(gridinfo_def),INTENT(inout) :: gridinfo
991 INTEGER :: itime
992 INTEGER :: itimerange
993 INTEGER :: ilevel
994 INTEGER :: ivar
995 TYPE(grid_id),INTENT(in),OPTIONAL :: gaid_template
996 LOGICAL,INTENT(in),OPTIONAL :: clone
997 
998 TYPE(grid_id) :: gaid
999 LOGICAL :: usetemplate
1000 REAL,POINTER :: voldati(:,:)
1001 TYPE(datetime) :: correctedtime
1002 
1003 #ifdef DEBUG
1004 CALL l4f_category_log(this%category,l4f_debug,"export_to_gridinfo")
1005 #endif
1006 
1007 IF (.NOT.c_e(this%gaid(ilevel,itime,itimerange,ivar))) THEN
1008 #ifdef DEBUG
1009  CALL l4f_category_log(this%category,l4f_debug,"empty gaid found, skipping export")
1010 #endif
1011  RETURN
1012 ENDIF
1013 
1014 usetemplate = .false.
1015 IF (PRESENT(gaid_template)) THEN
1016  CALL copy(gaid_template, gaid)
1017 #ifdef DEBUG
1018  CALL l4f_category_log(this%category,l4f_debug,"template cloned to a new gaid")
1019 #endif
1020  usetemplate = c_e(gaid)
1021 ENDIF
1022 
1023 IF (.NOT.usetemplate) THEN
1024  IF (optio_log(clone)) THEN
1025  CALL copy(this%gaid(ilevel,itime,itimerange,ivar), gaid)
1026 #ifdef DEBUG
1027  CALL l4f_category_log(this%category,l4f_debug,"original gaid cloned to a new one")
1028 #endif
1029  ELSE
1030  gaid = this%gaid(ilevel,itime,itimerange,ivar)
1031  ENDIF
1032 ENDIF
1033 
1034 IF (this%time_definition == 1 .OR. this%time_definition == 2) THEN
1035  correctedtime = this%time(itime) - &
1036  timedelta_new(sec=this%timerange(itimerange)%p1)
1037 ELSE
1038  correctedtime = this%time(itime)
1039 ENDIF
1040 
1041 CALL init(gridinfo,gaid, this%griddim, correctedtime, this%timerange(itimerange), &
1042  this%level(ilevel), this%var(ivar))
1043 
1044 ! reset the gridinfo, bad but necessary at this point for encoding the field
1045 CALL export(gridinfo%griddim, gridinfo%gaid)
1046 ! encode the field
1047 IF (ASSOCIATED(this%voldati)) THEN
1048  CALL encode_gridinfo(gridinfo, this%voldati(:,:,ilevel,itime,itimerange,ivar))
1049 ELSE IF (usetemplate) THEN ! field must be forced into template in this case
1050  NULLIFY(voldati)
1051  CALL volgrid_get_vol_2d(this, ilevel, itime, itimerange, ivar, voldati)
1052  CALL encode_gridinfo(gridinfo, voldati)
1053  DEALLOCATE(voldati)
1054 ENDIF
1055 
1056 END SUBROUTINE export_to_gridinfo
1057 
1058 
1076 SUBROUTINE import_from_gridinfovv(this, gridinfov, dup_mode, clone, decode, &
1077  time_definition, anavar, categoryappend)
1078 TYPE(volgrid6d),POINTER :: this(:)
1079 TYPE(arrayof_gridinfo),INTENT(in) :: gridinfov
1080 INTEGER,INTENT(in),OPTIONAL :: dup_mode
1081 LOGICAL , INTENT(in),OPTIONAL :: clone
1082 LOGICAL,INTENT(in),OPTIONAL :: decode
1083 INTEGER,INTENT(IN),OPTIONAL :: time_definition
1084 CHARACTER(len=*),INTENT(IN),OPTIONAL :: anavar(:)
1085 CHARACTER(len=*),INTENT(in),OPTIONAL :: categoryappend
1086 
1087 INTEGER :: i, j, stallo
1088 INTEGER :: ngrid, ntime, ntimerange, nlevel, nvar, ltime_definition
1089 TYPE(l4f_handle) :: category
1090 CHARACTER(len=512) :: a_name
1091 TYPE(datetime),ALLOCATABLE :: correctedtime(:)
1092 LOGICAL,ALLOCATABLE :: isanavar(:)
1093 TYPE(vol7d_var) :: lvar
1094 TYPE(vol7d_timerange),ALLOCATABLE :: correctedtimerange(:)
1095 
1096 ! category temporanea (altrimenti non possiamo loggare)
1097 if (present(categoryappend))then
1098  call l4f_launcher(a_name,a_name_append=trim(subcategory)//"."//trim(categoryappend))
1099 else
1100  call l4f_launcher(a_name,a_name_append=trim(subcategory))
1101 endif
1102 category=l4f_category_get_handle(a_name)
1103 
1104 #ifdef DEBUG
1105 call l4f_category_log(category,l4f_debug,"start import_from_gridinfovv")
1106 #endif
1107 
1108 IF (PRESENT(time_definition)) THEN
1109  ltime_definition = max(min(time_definition, 2), 0)
1110 ELSE
1111  ltime_definition = 0
1112 ENDIF
1113 
1114 ngrid=count_distinct(gridinfov%array(1:gridinfov%arraysize)%griddim,back=.true.)
1115 CALL l4f_category_log(category,l4f_info, t2c(ngrid)// &
1116  ' different grid definition(s) found in input data')
1117 
1118 ALLOCATE(this(ngrid),stat=stallo)
1119 IF (stallo /= 0)THEN
1120  CALL l4f_category_log(category,l4f_fatal,"allocating memory")
1121  CALL raise_fatal_error()
1122 ENDIF
1123 DO i = 1, ngrid
1124  IF (PRESENT(categoryappend))THEN
1125  CALL init(this(i), time_definition=ltime_definition, categoryappend=trim(categoryappend)//"-vol"//t2c(i))
1126  ELSE
1127  CALL init(this(i), time_definition=ltime_definition, categoryappend="vol"//t2c(i))
1128  ENDIF
1129 ENDDO
1130 
1131 this(:)%griddim=pack_distinct(gridinfov%array(1:gridinfov%arraysize)%griddim, &
1132  ngrid, back=.true.)
1133 
1134 ! mark elements as ana variables (time-independent)
1135 ALLOCATE(isanavar(gridinfov%arraysize))
1136 isanavar(:) = .false.
1137 IF (PRESENT(anavar)) THEN
1138  DO i = 1, gridinfov%arraysize
1139  DO j = 1, SIZE(anavar)
1140  lvar = convert(gridinfov%array(i)%var)
1141  IF (lvar%btable == anavar(j)) THEN
1142  isanavar(i) = .true.
1143  EXIT
1144  ENDIF
1145  ENDDO
1146  ENDDO
1147  CALL l4f_category_log(category,l4f_info,t2c(count(isanavar))//'/'// &
1148  t2c(gridinfov%arraysize)//' constant-data messages found in input data')
1149 ENDIF
1150 
1151 IF (ltime_definition == 1 .OR. ltime_definition == 2) THEN ! verification time
1152  ALLOCATE(correctedtime(gridinfov%arraysize))
1153  correctedtime(:) = gridinfov%array(1:gridinfov%arraysize)%time
1154  DO i = 1, gridinfov%arraysize
1155  correctedtime(i) = correctedtime(i) + &
1156  timedelta_new(sec=gridinfov%array(i)%timerange%p1)
1157  ENDDO
1158 ENDIF
1159 IF (ltime_definition == 2) THEN ! set all to analysis
1160  ALLOCATE(correctedtimerange(gridinfov%arraysize))
1161  correctedtimerange(:) = gridinfov%array(1:gridinfov%arraysize)%timerange
1162  correctedtimerange(:)%p1 = 0
1163 ENDIF
1164 
1165 DO i = 1, ngrid
1166  IF (PRESENT(anavar)) THEN
1167  j = count((this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim) &
1168  .AND. .NOT.isanavar(:))
1169  IF (j <= 0) THEN
1170  CALL l4f_category_log(category, l4f_fatal, 'grid n.'//t2c(i)// &
1171  ' has only constant data, this is not allowed')
1172  CALL l4f_category_log(category, l4f_fatal, 'please check anavar argument')
1173  CALL raise_fatal_error()
1174  ENDIF
1175  ENDIF
1176  IF (ltime_definition == 1 .OR. ltime_definition == 2) THEN ! verification time
1177  ntime = count_distinct(correctedtime, &
1178  mask=(this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim) &
1179  .AND. .NOT.isanavar(:), back=.true.)
1180  ELSE
1181  ntime = count_distinct(gridinfov%array(1:gridinfov%arraysize)%time, &
1182  mask=(this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim) &
1183  .AND. .NOT.isanavar(:), back=.true.)
1184  ENDIF
1185  IF (ltime_definition == 2) THEN ! set all to analysis
1186  ntimerange = count_distinct(correctedtimerange, &
1187  mask=(this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim) &
1188  .AND. .NOT.isanavar(:), back=.true.)
1189  ELSE
1190  ntimerange = count_distinct(gridinfov%array(1:gridinfov%arraysize)%timerange, &
1191  mask=(this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim) &
1192  .AND. .NOT.isanavar(:), back=.true.)
1193  ENDIF
1194  nlevel = count_distinct(gridinfov%array(1:gridinfov%arraysize)%level, &
1195  mask=(this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim), &
1196  back=.true.)
1197  nvar = count_distinct(gridinfov%array(1:gridinfov%arraysize)%var, &
1198  mask=(this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim), &
1199  back=.true.)
1200 
1201 #ifdef DEBUG
1202  CALL l4f_category_log(this(i)%category,l4f_debug,"alloc volgrid6d index: "//t2c(i))
1203 #endif
1204 
1205  CALL volgrid6d_alloc(this(i),this(i)%griddim%dim,ntime=ntime, &
1206  ntimerange=ntimerange,nlevel=nlevel,nvar=nvar)
1207 
1208  IF (ltime_definition == 1 .OR. ltime_definition == 2) THEN ! verification time
1209  this(i)%time = pack_distinct(correctedtime, ntime, &
1210  mask=(this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim) &
1211  .AND. .NOT.isanavar(:), back=.true.)
1212  ELSE
1213  this(i)%time = pack_distinct(gridinfov%array(1:gridinfov%arraysize)%time, ntime, &
1214  mask=(this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim) &
1215  .AND. .NOT.isanavar(:), back=.true.)
1216  ENDIF
1217  CALL sort(this(i)%time)
1218 
1219  IF (ltime_definition == 2) THEN ! set all to analysis
1220  this(i)%timerange = pack_distinct(correctedtimerange, ntimerange, &
1221  mask=(this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim) &
1222  .AND. .NOT.isanavar(:), back=.true.)
1223  ELSE
1224  this(i)%timerange = pack_distinct(gridinfov%array(1:gridinfov%arraysize)%timerange, &
1225  ntimerange, mask=(this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim) &
1226  .AND. .NOT.isanavar(:), back=.true.)
1227  ENDIF
1228  CALL sort(this(i)%timerange)
1229 
1230  this(i)%level=pack_distinct(gridinfov%array(1:gridinfov%arraysize)%level, &
1231  nlevel,mask=(this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim), &
1232  back=.true.)
1233  CALL sort(this(i)%level)
1234 
1235  this(i)%var=pack_distinct(gridinfov%array(1:gridinfov%arraysize)%var, nvar, &
1236  mask=(this(i)%griddim == gridinfov%array(1:gridinfov%arraysize)%griddim), &
1237  back=.true.)
1238 
1239 #ifdef DEBUG
1240  CALL l4f_category_log(this(i)%category,l4f_debug,"alloc_vol volgrid6d index: "//t2c(i))
1241 #endif
1242  CALL volgrid6d_alloc_vol(this(i), decode=decode)
1243 
1244 ENDDO
1245 
1246 IF (ltime_definition == 1 .OR. ltime_definition == 2) DEALLOCATE(correctedtime)
1247 IF (ltime_definition == 2) DEALLOCATE(correctedtimerange)
1248 
1249 DO i = 1, gridinfov%arraysize
1250 
1251 #ifdef DEBUG
1252  CALL l4f_category_log(category,l4f_debug,"import from gridinfov index: "//t2c(i))
1253  CALL l4f_category_log(category,l4f_info, &
1254  "to volgrid6d index: "//t2c(index(this%griddim, gridinfov%array(i)%griddim)))
1255 #endif
1256 
1257  CALL import(this(index(this%griddim, gridinfov%array(i)%griddim)), &
1258  gridinfov%array(i), dup_mode=dup_mode, clone=clone, isanavar=isanavar(i))
1259 
1260 ENDDO
1261 
1262 !chiudo il logger temporaneo
1263 CALL l4f_category_delete(category)
1264 
1265 END SUBROUTINE import_from_gridinfovv
1266 
1267 
1273 SUBROUTINE export_to_gridinfov(this, gridinfov, gaid_template, clone)
1274 TYPE(volgrid6d),INTENT(inout) :: this
1275 TYPE(arrayof_gridinfo),INTENT(inout) :: gridinfov
1276 TYPE(grid_id),INTENT(in),OPTIONAL :: gaid_template
1277 LOGICAL,INTENT(in),OPTIONAL :: clone
1278 
1279 INTEGER :: i ,itime, itimerange, ilevel, ivar
1280 INTEGER :: ntime, ntimerange, nlevel, nvar
1281 TYPE(gridinfo_def) :: gridinfol
1282 
1283 #ifdef DEBUG
1284 CALL l4f_category_log(this%category,l4f_debug,"start export_to_gridinfov")
1285 #endif
1286 
1287 ! this is necessary in order not to repeatedly and uselessly copy the
1288 ! same array of coordinates for each 2d grid during export, the
1289 ! side-effect is that the computed projection in this is lost
1290 CALL dealloc(this%griddim%dim)
1291 
1292 i=0
1293 ntime=size(this%time)
1294 ntimerange=size(this%timerange)
1295 nlevel=size(this%level)
1296 nvar=size(this%var)
1297 
1298 DO itime=1,ntime
1299  DO itimerange=1,ntimerange
1300  DO ilevel=1,nlevel
1301  DO ivar=1,nvar
1302 
1303  CALL init(gridinfol)
1304  CALL export(this, gridinfol, itime, itimerange, ilevel, ivar, &
1305  gaid_template=gaid_template, clone=clone)
1306  IF (c_e(gridinfol%gaid)) THEN
1307  CALL insert(gridinfov, gridinfol)
1308  ELSE
1309  CALL delete(gridinfol)
1310  ENDIF
1311 
1312  ENDDO
1313  ENDDO
1314  ENDDO
1315 ENDDO
1316 
1317 END SUBROUTINE export_to_gridinfov
1318 
1319 
1325 SUBROUTINE export_to_gridinfovv(this, gridinfov, gaid_template, clone)
1326 !, &
1327 ! categoryappend)
1328 TYPE(volgrid6d),INTENT(inout) :: this(:)
1329 TYPE(arrayof_gridinfo),INTENT(inout) :: gridinfov
1330 TYPE(grid_id),INTENT(in),OPTIONAL :: gaid_template
1331 LOGICAL,INTENT(in),OPTIONAL :: clone
1332 
1333 INTEGER :: i
1334 
1335 DO i = 1, SIZE(this)
1336 #ifdef DEBUG
1337  CALL l4f_category_log(this(i)%category,l4f_debug, &
1338  "export_to_gridinfovv grid index: "//t2c(i))
1339 #endif
1340  CALL export(this(i), gridinfov, gaid_template=gaid_template, clone=clone)
1341 ENDDO
1342 
1343 END SUBROUTINE export_to_gridinfovv
1344 
1345 
1355 SUBROUTINE volgrid6d_import_from_file(this, filename, dup_mode, decode, &
1356  time_definition, anavar, categoryappend)
1357 TYPE(volgrid6d),POINTER :: this(:)
1358 CHARACTER(len=*),INTENT(in) :: filename
1359 INTEGER,INTENT(in),OPTIONAL :: dup_mode
1360 LOGICAL,INTENT(in),OPTIONAL :: decode
1361 INTEGER,INTENT(IN),OPTIONAL :: time_definition
1362 CHARACTER(len=*),INTENT(IN),OPTIONAL :: anavar(:)
1363 character(len=*),INTENT(in),OPTIONAL :: categoryappend
1364 
1365 TYPE(arrayof_gridinfo) :: gridinfo
1366 TYPE(l4f_handle) :: category
1367 CHARACTER(len=512) :: a_name
1368 
1369 NULLIFY(this)
1370 
1371 IF (PRESENT(categoryappend))THEN
1372  CALL l4f_launcher(a_name,a_name_append= &
1373  trim(subcategory)//"."//trim(categoryappend))
1374 ELSE
1375  CALL l4f_launcher(a_name,a_name_append=trim(subcategory))
1376 ENDIF
1377 category=l4f_category_get_handle(a_name)
1378 
1379 CALL import(gridinfo, filename=filename, categoryappend=categoryappend)
1380 
1381 IF (gridinfo%arraysize > 0) THEN
1382 
1383  CALL import(this, gridinfo, dup_mode=dup_mode, clone=.true., decode=decode, &
1384  time_definition=time_definition, anavar=anavar, &
1385  categoryappend=categoryappend)
1386 
1387  CALL l4f_category_log(category,l4f_info,"deleting gridinfo")
1388  CALL delete(gridinfo)
1389 
1390 ELSE
1391  CALL l4f_category_log(category,l4f_info,"file does not contain gridded data")
1392 ENDIF
1393 
1394 ! close logger
1395 CALL l4f_category_delete(category)
1396 
1397 END SUBROUTINE volgrid6d_import_from_file
1398 
1399 
1407 SUBROUTINE volgrid6d_export_to_file(this, filename, gaid_template, categoryappend)
1408 TYPE(volgrid6d) :: this(:)
1409 CHARACTER(len=*),INTENT(in) :: filename
1410 TYPE(grid_id),INTENT(in),OPTIONAL :: gaid_template
1411 character(len=*),INTENT(in),OPTIONAL :: categoryappend
1412 
1413 TYPE(arrayof_gridinfo) :: gridinfo
1414 TYPE(l4f_handle) :: category
1415 CHARACTER(len=512) :: a_name
1416 
1417 IF (PRESENT(categoryappend)) THEN
1418  CALL l4f_launcher(a_name,a_name_append=trim(subcategory)//"."//trim(categoryappend))
1419 ELSE
1420  CALL l4f_launcher(a_name,a_name_append=trim(subcategory))
1421 ENDIF
1422 category=l4f_category_get_handle(a_name)
1423 
1424 #ifdef DEBUG
1425 CALL l4f_category_log(category,l4f_debug,"start export to file")
1426 #endif
1427 
1428 CALL l4f_category_log(category,l4f_info,"writing volgrid6d to grib file: "//trim(filename))
1429 
1430 !IF (ASSOCIATED(this)) THEN
1431  CALL export(this, gridinfo, gaid_template=gaid_template, clone=.true.)
1432  IF (gridinfo%arraysize > 0) THEN
1433  CALL export(gridinfo, filename)
1434  CALL delete(gridinfo)
1435  ENDIF
1436 !ELSE
1437 ! CALL l4f_category_log(category,L4F_INFO,"volume volgrid6d is not associated")
1438 !ENDIF
1439 
1440 ! close logger
1441 CALL l4f_category_delete(category)
1442 
1443 END SUBROUTINE volgrid6d_export_to_file
1444 
1445 
1449 SUBROUTINE volgrid6dv_delete(this)
1450 TYPE(volgrid6d),POINTER :: this(:)
1451 
1452 INTEGER :: i
1453 
1454 IF (ASSOCIATED(this)) THEN
1455  DO i = 1, SIZE(this)
1456 #ifdef DEBUG
1457  CALL l4f_category_log(this(i)%category,l4f_debug, &
1458  "delete volgrid6d vector index: "//trim(to_char(i)))
1459 #endif
1460  CALL delete(this(i))
1461  ENDDO
1462  DEALLOCATE(this)
1463 ENDIF
1464 
1465 END SUBROUTINE volgrid6dv_delete
1466 
1467 
1468 ! Internal method for performing grid to grid computations
1469 SUBROUTINE volgrid6d_transform_compute(this, volgrid6d_in, volgrid6d_out, &
1470  lev_out, var_coord_vol, clone)
1471 TYPE(grid_transform),INTENT(in) :: this ! oggetto di trasformazione per il grigliato
1472 type(volgrid6d), INTENT(in) :: volgrid6d_in ! oggetto da trasformare
1473 type(volgrid6d), INTENT(inout) :: volgrid6d_out ! oggetto trasformato; deve essere completo (init, alloc, alloc_vol)
1474 TYPE(vol7d_level),INTENT(in),OPTIONAL :: lev_out(:) ! vol7d_level object defining target vertical grid, for vertical interpolations
1475 INTEGER,INTENT(in),OPTIONAL :: var_coord_vol ! index of variable defining vertical coordinate values in input volume
1476 LOGICAL,INTENT(in),OPTIONAL :: clone ! se fornito e \c .TRUE., clona i gaid da volgrid6d_in a volgrid6d_out
1477 
1478 INTEGER :: ntime, ntimerange, inlevel, onlevel, nvar, &
1479  itime, itimerange, ilevel, ivar, levshift, levused, lvar_coord_vol, spos
1480 REAL,POINTER :: voldatiin(:,:,:), voldatiout(:,:,:), coord_3d_in(:,:,:)
1481 TYPE(vol7d_level) :: output_levtype
1482 LOGICAL,ALLOCATABLE :: zlist(:)
1483 
1484 
1485 #ifdef DEBUG
1486 call l4f_category_log(volgrid6d_in%category,l4f_debug,"start volgrid6d_transform_compute")
1487 #endif
1488 
1489 ntime=0
1490 ntimerange=0
1491 inlevel=0
1492 onlevel=0
1493 nvar=0
1494 lvar_coord_vol = optio_i(var_coord_vol)
1495 
1496 if (associated(volgrid6d_in%time))then
1497  ntime=size(volgrid6d_in%time)
1498  volgrid6d_out%time=volgrid6d_in%time
1499 end if
1500 
1501 if (associated(volgrid6d_in%timerange))then
1502  ntimerange=size(volgrid6d_in%timerange)
1503  volgrid6d_out%timerange=volgrid6d_in%timerange
1504 end if
1505 
1506 IF (ASSOCIATED(volgrid6d_in%level))THEN
1507  inlevel=SIZE(volgrid6d_in%level)
1508 ENDIF
1509 IF (PRESENT(lev_out)) THEN
1510  onlevel=SIZE(lev_out)
1511  volgrid6d_out%level=lev_out
1512 ELSE IF (ASSOCIATED(volgrid6d_in%level))THEN
1513  onlevel=SIZE(volgrid6d_in%level)
1514  volgrid6d_out%level=volgrid6d_in%level
1515 ENDIF
1516 
1517 if (associated(volgrid6d_in%var))then
1518  nvar=size(volgrid6d_in%var)
1519  volgrid6d_out%var=volgrid6d_in%var
1520 end if
1521 ! allocate once for speed
1522 IF (.NOT.ASSOCIATED(volgrid6d_in%voldati)) THEN
1523  ALLOCATE(voldatiin(volgrid6d_in%griddim%dim%nx, volgrid6d_in%griddim%dim%ny, &
1524  inlevel))
1525 ENDIF
1526 IF (.NOT.ASSOCIATED(volgrid6d_out%voldati)) THEN
1527  ALLOCATE(voldatiout(volgrid6d_out%griddim%dim%nx, volgrid6d_out%griddim%dim%ny, &
1528  onlevel))
1529 ENDIF
1530 
1531 CALL get_val(this, levshift=levshift, levused=levused)
1532 spos = imiss
1533 IF (c_e(lvar_coord_vol)) THEN
1534  CALL get_val(this%trans, output_levtype=output_levtype)
1535  IF (output_levtype%level1 == 103 .OR. output_levtype%level1 == 108) THEN
1536 ! here, unlike below, level (1,101) is not accepted because this is
1537 ! likely for pressure difference with surface 108, not 103
1538  spos = firsttrue(volgrid6d_in%level(:) == vol7d_level_new(1))
1539  IF (spos == 0) THEN
1540  CALL l4f_category_log(volgrid6d_in%category, l4f_error, &
1541  'output level '//t2c(output_levtype%level1)// &
1542  ' requested, but height/press of surface not provided in volume')
1543  ENDIF
1544  IF (.NOT.c_e(levshift) .AND. .NOT.c_e(levused)) THEN
1545  CALL l4f_category_log(volgrid6d_in%category, l4f_error, &
1546  'internal inconsistence, levshift and levused undefined when they should be')
1547  ENDIF
1548  ENDIF
1549 ENDIF
1550 
1551 DO ivar=1,nvar
1552 ! IF (c_e(var_coord_vol)) THEN
1553 ! IF (ivar == var_coord_vol) CYCLE ! skip coordinate variable in output
1554 ! ENDIF
1555  DO itimerange=1,ntimerange
1556  DO itime=1,ntime
1557 ! skip empty columns where possible, improve
1558  IF (c_e(levshift) .AND. c_e(levused)) THEN
1559  IF (.NOT.any(c_e( &
1560  volgrid6d_in%gaid(levshift+1:levshift+levused,itime,itimerange,ivar) &
1561  ))) cycle
1562  ENDIF
1563  DO ilevel = 1, min(inlevel,onlevel)
1564 ! if present gaid copy it
1565  IF (c_e(volgrid6d_in%gaid(ilevel,itime,itimerange,ivar)) .AND. .NOT. &
1566  c_e(volgrid6d_out%gaid(ilevel,itime,itimerange,ivar))) THEN
1567 
1568  IF (optio_log(clone)) THEN
1569  CALL copy(volgrid6d_in%gaid(ilevel,itime,itimerange,ivar),&
1570  volgrid6d_out%gaid(ilevel,itime,itimerange,ivar))
1571 #ifdef DEBUG
1572  CALL l4f_category_log(volgrid6d_in%category,l4f_debug, &
1573  "cloning gaid, level "//t2c(ilevel))
1574 #endif
1575  ELSE
1576  volgrid6d_out%gaid(ilevel,itime,itimerange,ivar) = &
1577  volgrid6d_in%gaid(ilevel,itime,itimerange,ivar)
1578  ENDIF
1579  ENDIF
1580  ENDDO
1581 ! if out level are more, we have to clone anyway
1582  DO ilevel = min(inlevel,onlevel) + 1, onlevel
1583  IF (c_e(volgrid6d_in%gaid(inlevel,itime,itimerange,ivar)) .AND. .NOT. &
1584  c_e(volgrid6d_out%gaid(ilevel,itime,itimerange,ivar))) then
1585 
1586  CALL copy(volgrid6d_in%gaid(inlevel,itime,itimerange,ivar),&
1587  volgrid6d_out%gaid(ilevel,itime,itimerange,ivar))
1588 #ifdef DEBUG
1589  CALL l4f_category_log(volgrid6d_in%category,l4f_debug, &
1590  "forced cloning gaid, level "//t2c(inlevel)//"->"//t2c(ilevel))
1591 #endif
1592  ENDIF
1593  ENDDO
1594 
1595  IF (c_e(lvar_coord_vol)) THEN
1596  NULLIFY(coord_3d_in)
1597  CALL volgrid_get_vol_3d(volgrid6d_in, itime, itimerange, lvar_coord_vol, &
1598  coord_3d_in)
1599  IF (c_e(spos)) THEN ! compute difference wrt surface coordinate
1600  IF (spos == 0) THEN ! error condition, set all to missing and goodnight
1601  coord_3d_in(:,:,levshift+1:levshift+levused) = rmiss
1602  ELSE
1603  DO ilevel = levshift+1, levshift+levused
1604  WHERE(c_e(coord_3d_in(:,:,ilevel)) .AND. c_e(coord_3d_in(:,:,spos)))
1605  coord_3d_in(:,:,ilevel) = coord_3d_in(:,:,ilevel) - &
1606  coord_3d_in(:,:,spos)
1607  ELSEWHERE
1608  coord_3d_in(:,:,ilevel) = rmiss
1609  END WHERE
1610  ENDDO
1611  ENDIF
1612  ENDIF
1613  ENDIF
1614  CALL volgrid_get_vol_3d(volgrid6d_in, itime, itimerange, ivar, &
1615  voldatiin, zlist)
1616  IF (ASSOCIATED(volgrid6d_out%voldati)) & ! improve!!!!
1617  CALL volgrid_get_vol_3d(volgrid6d_out, itime, itimerange, ivar, &
1618  voldatiout)
1619  IF (c_e(lvar_coord_vol)) THEN ! this is a vertint case, zlist is useless
1620  CALL compute(this, voldatiin, voldatiout, var=convert(volgrid6d_in%var(ivar)), &
1621  coord_3d_in=coord_3d_in(:,:,levshift+1:levshift+levused)) ! subset coord_3d_in
1622  ELSE
1623  CALL compute(this, voldatiin, voldatiout, var=convert(volgrid6d_in%var(ivar)), zlist=zlist)
1624  ENDIF
1625  CALL volgrid_set_vol_3d(volgrid6d_out, itime, itimerange, ivar, &
1626  voldatiout)
1627  ENDDO
1628  ENDDO
1629 ENDDO
1630 
1631 IF (c_e(lvar_coord_vol)) THEN
1632  DEALLOCATE(coord_3d_in)
1633 ENDIF
1634 IF (.NOT.ASSOCIATED(volgrid6d_in%voldati)) THEN
1635  DEALLOCATE(voldatiin)
1636 ENDIF
1637 IF (.NOT.ASSOCIATED(volgrid6d_out%voldati)) THEN
1638  DEALLOCATE(voldatiout)
1639 ENDIF
1640 
1641 
1642 END SUBROUTINE volgrid6d_transform_compute
1643 
1644 
1651 SUBROUTINE volgrid6d_transform(this, griddim, volgrid6d_in, volgrid6d_out, &
1652  lev_out, volgrid6d_coord_in, maskgrid, maskbounds, clone, decode, categoryappend)
1653 TYPE(transform_def),INTENT(in) :: this
1654 TYPE(griddim_def),INTENT(in),OPTIONAL :: griddim
1655 TYPE(volgrid6d),INTENT(inout) :: volgrid6d_in
1656 TYPE(volgrid6d),INTENT(out) :: volgrid6d_out
1657 TYPE(vol7d_level),INTENT(in),OPTIONAL,TARGET :: lev_out(:)
1658 TYPE(volgrid6d),INTENT(in),OPTIONAL :: volgrid6d_coord_in
1659 REAL,INTENT(in),OPTIONAL :: maskgrid(:,:)
1660 REAL,INTENT(in),OPTIONAL :: maskbounds(:)
1661 LOGICAL,INTENT(in),OPTIONAL :: clone
1662 LOGICAL,INTENT(in),OPTIONAL :: decode
1663 CHARACTER(len=*),INTENT(in),OPTIONAL :: categoryappend
1664 
1665 TYPE(grid_transform) :: grid_trans
1666 TYPE(vol7d_level),POINTER :: llev_out(:)
1667 TYPE(vol7d_level) :: input_levtype, output_levtype
1668 TYPE(vol7d_var) :: vcoord_var
1669 INTEGER :: i, k, ntime, ntimerange, nlevel, nvar, var_coord_in, var_coord_vol, &
1670  cf_out, nxc, nyc, nxi, nyi, i3, i4, i5, i6, &
1671  ulstart, ulend, spos
1672 REAL,ALLOCATABLE :: coord_3d_in(:,:,:)
1673 TYPE(geo_proj) :: proj_in, proj_out
1674 CHARACTER(len=80) :: trans_type
1675 LOGICAL :: ldecode
1676 LOGICAL,ALLOCATABLE :: mask_in(:)
1677 
1678 #ifdef DEBUG
1679 call l4f_category_log(volgrid6d_in%category, l4f_debug, "start volgrid6d_transform")
1680 #endif
1681 
1682 ntime=0
1683 ntimerange=0
1684 nlevel=0
1685 nvar=0
1686 
1687 if (associated(volgrid6d_in%time)) ntime=size(volgrid6d_in%time)
1688 if (associated(volgrid6d_in%timerange)) ntimerange=size(volgrid6d_in%timerange)
1689 if (associated(volgrid6d_in%level)) nlevel=size(volgrid6d_in%level)
1690 if (associated(volgrid6d_in%var)) nvar=size(volgrid6d_in%var)
1691 
1692 IF (ntime == 0 .OR. ntimerange == 0 .OR. nlevel == 0 .OR. nvar == 0) THEN
1693  CALL l4f_category_log(volgrid6d_in%category, l4f_error, &
1694  "trying to transform an incomplete volgrid6d object, ntime="//t2c(ntime)// &
1695  ' ntimerange='//t2c(ntimerange)//' nlevel='//t2c(nlevel)//' nvar='//t2c(nvar))
1696  CALL init(volgrid6d_out) ! initialize to empty
1697  CALL raise_error()
1698  RETURN
1699 ENDIF
1700 
1701 CALL get_val(this, trans_type=trans_type)
1702 
1703 ! store desired output component flag and unrotate if necessary
1704 cf_out = imiss
1705 IF (PRESENT(griddim) .AND. (trans_type == 'inter' .OR. trans_type == 'boxinter' &
1706  .OR. trans_type == 'stencilinter')) THEN ! improve condition!!
1707  CALL get_val(volgrid6d_in%griddim, proj=proj_in)
1708  CALL get_val(griddim, component_flag=cf_out, proj=proj_out)
1709 ! if different projections wind components must be referred to geographical system
1710  IF (proj_in /= proj_out) CALL vg6d_wind_unrot(volgrid6d_in)
1711 ELSE IF (PRESENT(griddim)) THEN ! just get component_flag, the rest is rubbish
1712  CALL get_val(griddim, component_flag=cf_out)
1713 ENDIF
1714 
1715 
1716 var_coord_in = imiss
1717 var_coord_vol = imiss
1718 IF (trans_type == 'vertint') THEN
1719  IF (PRESENT(lev_out)) THEN
1720 
1721 ! if volgrid6d_coord_in provided and allocated, check that it fits
1722  IF (PRESENT(volgrid6d_coord_in)) THEN
1723  IF (ASSOCIATED(volgrid6d_coord_in%voldati)) THEN
1724 
1725 ! strictly 1 time and 1 timerange
1726  IF (SIZE(volgrid6d_coord_in%voldati,4) /= 1 .OR. &
1727  SIZE(volgrid6d_coord_in%voldati,5) /= 1) THEN
1728  CALL l4f_category_log(volgrid6d_in%category, l4f_error, &
1729  'volume providing constant input vertical coordinate must have &
1730  &only 1 time and 1 timerange')
1731  CALL init(volgrid6d_out) ! initialize to empty
1732  CALL raise_error()
1733  RETURN
1734  ENDIF
1735 
1736 ! search for variable providing vertical coordinate
1737  CALL get_val(this, output_levtype=output_levtype)
1738  vcoord_var = vol7d_var_new(vol7d_level_to_var(output_levtype))
1739  IF (.NOT.c_e(vcoord_var)) THEN
1740  CALL l4f_category_log(volgrid6d_in%category, l4f_error, &
1741  'requested output level type '//t2c(output_levtype%level1)// &
1742  ' does not correspond to any known physical variable for &
1743  &providing vertical coordinate')
1744  CALL init(volgrid6d_out) ! initialize to empty
1745  CALL raise_error()
1746  RETURN
1747  ENDIF
1748 
1749  DO i = 1, SIZE(volgrid6d_coord_in%var)
1750  IF (convert(volgrid6d_coord_in%var(i)) == vcoord_var) THEN
1751  var_coord_in = i
1752  EXIT
1753  ENDIF
1754  ENDDO
1755 
1756  IF (.NOT.c_e(var_coord_in)) THEN
1757  CALL l4f_category_log(volgrid6d_in%category, l4f_error, &
1758  'volume providing constant input vertical coordinate contains no &
1759  &variables matching output level type '//t2c(output_levtype%level1))
1760  CALL init(volgrid6d_out) ! initialize to empty
1761  CALL raise_error()
1762  RETURN
1763  ENDIF
1764  CALL l4f_category_log(volgrid6d_in%category, l4f_info, &
1765  'Coordinate for vertint found in coord volume at position '// &
1766  t2c(var_coord_in))
1767 
1768 ! check horizontal grid
1769 ! this is too strict (component flag and so on)
1770 ! IF (volgrid6d_coord_in%griddim /= volgrid6d_in%griddim) THEN
1771  CALL get_val(volgrid6d_coord_in%griddim, nx=nxc, ny=nyc)
1772  CALL get_val(volgrid6d_in%griddim, nx=nxi, ny=nyi)
1773  IF (nxc /= nxi .OR. nyc /= nyi) THEN
1774  CALL l4f_category_log(volgrid6d_in%category, l4f_error, &
1775  'volume providing constant input vertical coordinate must have &
1776  &the same grid as the input')
1777  CALL l4f_category_log(volgrid6d_in%category, l4f_error, &
1778  'vertical coordinate: '//t2c(nxc)//'x'//t2c(nyc)// &
1779  ', input volume: '//t2c(nxi)//'x'//t2c(nyi))
1780  CALL init(volgrid6d_out) ! initialize to empty
1781  CALL raise_error()
1782  RETURN
1783  ENDIF
1784 
1785 ! check vertical coordinate system
1786  CALL get_val(this, input_levtype=input_levtype)
1787  mask_in = & ! implicit allocation
1788  (volgrid6d_coord_in%level(:)%level1 == input_levtype%level1) .AND. &
1789  (volgrid6d_coord_in%level(:)%level2 == input_levtype%level2)
1790  ulstart = firsttrue(mask_in)
1791  ulend = lasttrue(mask_in)
1792  IF (ulstart == 0 .OR. ulend == 0) THEN
1793  CALL l4f_category_log(volgrid6d_in%category, l4f_error, &
1794  'coordinate file does not contain levels of type '// &
1795  t2c(input_levtype%level1)//'/'//t2c(input_levtype%level2)// &
1796  ' specified for input data')
1797  CALL init(volgrid6d_out) ! initialize to empty
1798  CALL raise_error()
1799  RETURN
1800  ENDIF
1801 
1802  coord_3d_in = volgrid6d_coord_in%voldati(:,:,ulstart:ulend,1,1,var_coord_in) ! implicit allocation
1803 ! special case
1804  IF (output_levtype%level1 == 103 .OR. &
1805  output_levtype%level1 == 108) THEN ! surface coordinate needed
1806 ! allow coding of orography level as in Icon
1807  spos = firsttrue(volgrid6d_coord_in%level(:) == vol7d_level_new(level1=1) .OR. &
1808  volgrid6d_coord_in%level(:) == vol7d_level_new(level1=1, level2=101))
1809  IF (spos == 0) THEN
1810  CALL l4f_category_log(volgrid6d_in%category, l4f_error, &
1811  'output level '//t2c(output_levtype%level1)// &
1812  ' requested, but height/press of surface not provided in coordinate file')
1813  CALL init(volgrid6d_out) ! initialize to empty
1814  CALL raise_error()
1815  RETURN
1816  ENDIF
1817  DO k = 1, SIZE(coord_3d_in,3)
1818  WHERE(c_e(coord_3d_in(:,:,k)) .AND. &
1819  c_e(volgrid6d_coord_in%voldati(:,:,spos,1,1,var_coord_in)))
1820  coord_3d_in(:,:,k) = coord_3d_in(:,:,k) - &
1821  volgrid6d_coord_in%voldati(:,:,spos,1,1,var_coord_in)
1822  ELSEWHERE
1823  coord_3d_in(:,:,k) = rmiss
1824  END WHERE
1825  ENDDO
1826  ENDIF
1827 
1828  ENDIF
1829  ENDIF
1830 
1831  IF (.NOT.c_e(var_coord_in)) THEN ! search for coordinate within volume
1832 ! search for variable providing vertical coordinate
1833  CALL get_val(this, output_levtype=output_levtype)
1834  vcoord_var = vol7d_var_new(vol7d_level_to_var(output_levtype))
1835  IF (c_e(vcoord_var)) THEN
1836  DO i = 1, SIZE(volgrid6d_in%var)
1837  IF (convert(volgrid6d_in%var(i)) == vcoord_var) THEN
1838  var_coord_vol = i
1839  EXIT
1840  ENDIF
1841  ENDDO
1842 
1843  IF (c_e(var_coord_vol)) THEN
1844  CALL l4f_category_log(volgrid6d_in%category, l4f_info, &
1845  'Coordinate for vertint found in input volume at position '// &
1846  t2c(var_coord_vol))
1847  ENDIF
1848 
1849  ENDIF
1850  ENDIF
1852  CALL init(volgrid6d_out, griddim=volgrid6d_in%griddim, &
1853  time_definition=volgrid6d_in%time_definition, categoryappend=categoryappend)
1854  IF (c_e(var_coord_in)) THEN
1855  CALL init(grid_trans, this, lev_in=volgrid6d_in%level, lev_out=lev_out, &
1856  coord_3d_in=coord_3d_in, categoryappend=categoryappend)
1857  ELSE
1858  CALL init(grid_trans, this, lev_in=volgrid6d_in%level, lev_out=lev_out, &
1859  categoryappend=categoryappend)
1860  ENDIF
1861 
1862  CALL get_val(grid_trans, output_level_auto=llev_out) ! get levels if auto-generated
1863  IF (.NOT.ASSOCIATED(llev_out)) llev_out => lev_out
1864  nlevel = SIZE(llev_out)
1865  ELSE
1866  CALL l4f_category_log(volgrid6d_in%category, l4f_error, &
1867  'volgrid6d_transform: vertint requested but lev_out not provided')
1868  CALL init(volgrid6d_out) ! initialize to empty
1869  CALL raise_error()
1870  RETURN
1871  ENDIF
1872 
1873 ELSE
1874  CALL init(volgrid6d_out, griddim=griddim, &
1875  time_definition=volgrid6d_in%time_definition, categoryappend=categoryappend)
1876  CALL init(grid_trans, this, in=volgrid6d_in%griddim, out=volgrid6d_out%griddim, &
1877  maskgrid=maskgrid, maskbounds=maskbounds, categoryappend=categoryappend)
1878 ENDIF
1879 
1880 
1881 IF (c_e(grid_trans)) THEN ! transformation is valid
1882 
1883  CALL volgrid6d_alloc(volgrid6d_out, ntime=ntime, nlevel=nlevel, &
1884  ntimerange=ntimerange, nvar=nvar)
1885 
1886  IF (PRESENT(decode)) THEN ! explicitly set decode status
1887  ldecode = decode
1888  ELSE ! take it from input
1889  ldecode = ASSOCIATED(volgrid6d_in%voldati)
1890  ENDIF
1891 ! force decode if gaid is readonly
1892  decode_loop: DO i6 = 1,nvar
1893  DO i5 = 1, ntimerange
1894  DO i4 = 1, ntime
1895  DO i3 = 1, nlevel
1896  IF (c_e(volgrid6d_in%gaid(i3,i4,i5,i6))) THEN
1897  ldecode = ldecode .OR. grid_id_readonly(volgrid6d_in%gaid(i3,i4,i5,i6))
1898  EXIT decode_loop
1899  ENDIF
1900  ENDDO
1901  ENDDO
1902  ENDDO
1903  ENDDO decode_loop
1904 
1905  IF (PRESENT(decode)) THEN
1906  IF (ldecode.NEQV.decode) THEN
1907  CALL l4f_category_log(volgrid6d_in%category, l4f_warn, &
1908  'volgrid6d_transform: decode status forced to .TRUE. because driver does not allow copy')
1909  ENDIF
1910  ENDIF
1911 
1912  CALL volgrid6d_alloc_vol(volgrid6d_out, decode=ldecode)
1913 
1914 !ensure unproj was called
1915 !call griddim_unproj(volgrid6d_out%griddim)
1916 
1917  IF (trans_type == 'vertint') THEN
1918 #ifdef DEBUG
1919  CALL l4f_category_log(volgrid6d_in%category, l4f_debug, &
1920  "volgrid6d_transform: vertint to "//t2c(nlevel)//" levels")
1921 #endif
1922  CALL compute(grid_trans, volgrid6d_in, volgrid6d_out, lev_out=llev_out, &
1923  var_coord_vol=var_coord_vol, clone=clone)
1924  ELSE
1925  CALL compute(grid_trans, volgrid6d_in, volgrid6d_out, clone=clone)
1926  ENDIF
1927 
1928  IF (cf_out == 0) THEN ! unrotated components are desired
1929  CALL wind_unrot(volgrid6d_out) ! unrotate if necessary
1930  ELSE IF (cf_out == 1) THEN ! rotated components are desired
1931  CALL wind_rot(volgrid6d_out) ! rotate if necessary
1932  ENDIF
1933 
1934 ELSE
1935 ! should log with grid_trans%category, but it is private
1936  CALL l4f_category_log(volgrid6d_in%category, l4f_error, &
1937  'volgrid6d_transform: transformation not valid')
1938  CALL raise_error()
1939 ENDIF
1940 
1941 CALL delete (grid_trans)
1942 
1943 END SUBROUTINE volgrid6d_transform
1944 
1945 
1954 SUBROUTINE volgrid6dv_transform(this, griddim, volgrid6d_in, volgrid6d_out, &
1955  lev_out, volgrid6d_coord_in, maskgrid, maskbounds, clone, decode, categoryappend)
1956 TYPE(transform_def),INTENT(in) :: this
1957 TYPE(griddim_def),INTENT(in),OPTIONAL :: griddim
1958 TYPE(volgrid6d),INTENT(inout) :: volgrid6d_in(:)
1959 TYPE(volgrid6d),POINTER :: volgrid6d_out(:)
1960 TYPE(vol7d_level),INTENT(in),OPTIONAL :: lev_out(:)
1961 TYPE(volgrid6d),INTENT(in),OPTIONAL :: volgrid6d_coord_in
1962 REAL,INTENT(in),OPTIONAL :: maskgrid(:,:)
1963 REAL,INTENT(in),OPTIONAL :: maskbounds(:)
1964 LOGICAL,INTENT(in),OPTIONAL :: clone
1965 LOGICAL,INTENT(in),OPTIONAL :: decode
1966 CHARACTER(len=*),INTENT(in),OPTIONAL :: categoryappend
1967 
1968 INTEGER :: i, stallo
1969 
1970 
1971 allocate(volgrid6d_out(size(volgrid6d_in)),stat=stallo)
1972 if (stallo /= 0)then
1973  call l4f_log(l4f_fatal,"allocating memory")
1974  call raise_fatal_error()
1975 end if
1976 
1977 do i=1,size(volgrid6d_in)
1978  call transform(this, griddim, volgrid6d_in(i), volgrid6d_out(i), &
1979  lev_out=lev_out, volgrid6d_coord_in=volgrid6d_coord_in, &
1980  maskgrid=maskgrid, maskbounds=maskbounds, &
1981  clone=clone, decode=decode, categoryappend=categoryappend)
1982 end do
1983 
1984 END SUBROUTINE volgrid6dv_transform
1985 
1986 
1987 ! Internal method for performing grid to sparse point computations
1988 SUBROUTINE volgrid6d_v7d_transform_compute(this, volgrid6d_in, vol7d_out, &
1989  networkname, noconvert)
1990 TYPE(grid_transform),INTENT(in) :: this ! oggetto di trasformazione per grigliato
1991 type(volgrid6d), INTENT(in) :: volgrid6d_in ! oggetto da trasformare
1992 type(vol7d), INTENT(inout) :: vol7d_out ! oggetto trasformato
1993 CHARACTER(len=*),OPTIONAL,INTENT(in) :: networkname ! imposta il network in vol7d_out (default='generic')
1994 LOGICAL,OPTIONAL,INTENT(in) :: noconvert
1995 
1996 INTEGER :: nntime, nana, ntime, ntimerange, nlevel, nvar, stallo
1997 INTEGER :: itime, itimerange, ivar, inetwork
1998 REAL,ALLOCATABLE :: voldatir_out(:,:,:)
1999 TYPE(conv_func),POINTER :: c_func(:)
2000 TYPE(datetime),ALLOCATABLE :: validitytime(:,:)
2001 REAL,POINTER :: voldatiin(:,:,:)
2002 
2003 #ifdef DEBUG
2004 call l4f_category_log(volgrid6d_in%category,l4f_debug,"start volgrid6d_v7d_transform_compute")
2005 #endif
2006 
2007 ntime=0
2008 ntimerange=0
2009 nlevel=0
2010 nvar=0
2011 NULLIFY(c_func)
2012 
2013 if (present(networkname))then
2014  call init(vol7d_out%network(1),name=networkname)
2015 else
2016  call init(vol7d_out%network(1),name='generic')
2017 end if
2018 
2019 if (associated(volgrid6d_in%timerange))then
2020  ntimerange=size(volgrid6d_in%timerange)
2021  vol7d_out%timerange=volgrid6d_in%timerange
2022 end if
2023 
2024 if (associated(volgrid6d_in%time))then
2025  ntime=size(volgrid6d_in%time)
2026 
2027  if (vol7d_out%time_definition == volgrid6d_in%time_definition) then
2028 
2029  ! i time sono definiti uguali: assegno
2030  vol7d_out%time=volgrid6d_in%time
2031 
2032  else
2033  ! converto reference in validity
2034  allocate (validitytime(ntime,ntimerange),stat=stallo)
2035  if (stallo /=0)then
2036  call l4f_category_log(volgrid6d_in%category,l4f_fatal,"allocating memory")
2037  call raise_fatal_error()
2038  end if
2039 
2040  do itime=1,ntime
2041  do itimerange=1,ntimerange
2042  if (vol7d_out%time_definition > volgrid6d_in%time_definition) then
2043  validitytime(itime,itimerange) = &
2044  volgrid6d_in%time(itime) + timedelta_new(sec=volgrid6d_in%timerange(itimerange)%p1)
2045  else
2046  validitytime(itime,itimerange) = &
2047  volgrid6d_in%time(itime) - timedelta_new(sec=volgrid6d_in%timerange(itimerange)%p1)
2048  end if
2049  end do
2050  end do
2051 
2052  nntime = count_distinct(reshape(validitytime,(/ntime*ntimerange/)), back=.true.)
2053  vol7d_out%time=pack_distinct(reshape(validitytime,(/ntime*ntimerange/)), nntime,back=.true.)
2054 
2055  end if
2056 end if
2057 
2058 IF (ASSOCIATED(volgrid6d_in%level)) THEN
2059  nlevel = SIZE(volgrid6d_in%level)
2060  vol7d_out%level=volgrid6d_in%level
2061 ENDIF
2062 
2063 IF (ASSOCIATED(volgrid6d_in%var)) THEN
2064  nvar = SIZE(volgrid6d_in%var)
2065  IF (.NOT. optio_log(noconvert)) THEN
2066  CALL vargrib2varbufr(volgrid6d_in%var, vol7d_out%dativar%r, c_func)
2067  ENDIF
2068 ENDIF
2069 
2070 nana = SIZE(vol7d_out%ana)
2071 
2072 ! allocate once for speed
2073 IF (.NOT.ASSOCIATED(volgrid6d_in%voldati)) THEN
2074  ALLOCATE(voldatiin(volgrid6d_in%griddim%dim%nx, volgrid6d_in%griddim%dim%ny, &
2075  nlevel))
2076 ENDIF
2077 
2078 ALLOCATE(voldatir_out(nana,1,nlevel),stat=stallo)
2079 IF (stallo /= 0) THEN
2080  CALL l4f_category_log(volgrid6d_in%category,l4f_fatal,"allocating memory")
2081  CALL raise_fatal_error()
2082 ENDIF
2083 
2084 inetwork=1
2085 do itime=1,ntime
2086  do itimerange=1,ntimerange
2087 ! do ilevel=1,nlevel
2088  do ivar=1,nvar
2089 
2090  !non è chiaro se questa sezione è utile o no
2091  !ossia il compute sotto sembra prevedere voldatir_out solo in out
2092 !!$ if (vol7d_out%time_definition == volgrid6d_in%time_definition) then
2093 !!$ voldatir_out=reshape(vol7d_out%voldatir(:,itime,ilevel,itimerange,ivar,inetwork),(/nana,1/))
2094 !!$ else
2095 !!$ voldatir_out=reshape(vol7d_out%voldatir(:,index(vol7d_out%time,validitytime(itime,ilevel)),ilevel,itimerange,ivar,inetwork),(/nana,1/))
2096 !!$ end if
2097 
2098  CALL volgrid_get_vol_3d(volgrid6d_in, itime, itimerange, ivar, &
2099  voldatiin)
2100 
2101  CALL compute(this, voldatiin, voldatir_out, vol7d_out%dativar%r(ivar))
2102 
2103  if (vol7d_out%time_definition == volgrid6d_in%time_definition) then
2104  vol7d_out%voldatir(:,itime,:,itimerange,ivar,inetwork) = &
2105  voldatir_out(:,1,:)
2106  else
2107  vol7d_out%voldatir(:,index(vol7d_out%time,validitytime(itime,itimerange)),:,itimerange,ivar,inetwork)=&
2108  reshape(voldatir_out,(/nana,nlevel/))
2109  end if
2110 
2111 ! 1 indice della dimensione "anagrafica"
2112 ! 2 indice della dimensione "tempo"
2113 ! 3 indice della dimensione "livello verticale"
2114 ! 4 indice della dimensione "intervallo temporale"
2115 ! 5 indice della dimensione "variabile"
2116 ! 6 indice della dimensione "rete"
2117 
2118  end do
2119 ! end do
2120  end do
2121 end do
2122 
2123 deallocate(voldatir_out)
2124 IF (.NOT.ASSOCIATED(volgrid6d_in%voldati)) THEN
2125  DEALLOCATE(voldatiin)
2126 ENDIF
2127 if (allocated(validitytime)) deallocate(validitytime)
2128 
2129 ! Rescale valid data according to variable conversion table
2130 IF (ASSOCIATED(c_func)) THEN
2131  DO ivar = 1, nvar
2132  CALL compute(c_func(ivar), vol7d_out%voldatir(:,:,:,:,ivar,:))
2133  ENDDO
2134  DEALLOCATE(c_func)
2135 ENDIF
2136 
2137 end SUBROUTINE volgrid6d_v7d_transform_compute
2138 
2139 
2146 SUBROUTINE volgrid6d_v7d_transform(this, volgrid6d_in, vol7d_out, v7d, &
2147  maskgrid, maskbounds, networkname, noconvert, find_index, categoryappend)
2148 TYPE(transform_def),INTENT(in) :: this
2149 TYPE(volgrid6d),INTENT(inout) :: volgrid6d_in
2150 TYPE(vol7d),INTENT(out) :: vol7d_out
2151 TYPE(vol7d),INTENT(in),OPTIONAL :: v7d
2152 REAL,INTENT(in),OPTIONAL :: maskgrid(:,:)
2153 REAL,INTENT(in),OPTIONAL :: maskbounds(:)
2154 CHARACTER(len=*),OPTIONAL,INTENT(in) :: networkname
2155 LOGICAL,OPTIONAL,INTENT(in) :: noconvert
2156 PROCEDURE(basic_find_index),POINTER,OPTIONAL :: find_index
2157 CHARACTER(len=*),INTENT(in),OPTIONAL :: categoryappend
2158 
2159 type(grid_transform) :: grid_trans
2160 INTEGER :: ntime, ntimerange, nlevel, nvar, nana, time_definition, nnetwork, stallo
2161 INTEGER :: itime, itimerange, inetwork
2162 TYPE(datetime),ALLOCATABLE :: validitytime(:,:)
2163 INTEGER,ALLOCATABLE :: point_index(:)
2164 TYPE(vol7d) :: v7d_locana
2165 
2166 #ifdef DEBUG
2167 call l4f_category_log(volgrid6d_in%category,l4f_debug,"start volgrid6d_v7d_transform")
2168 #endif
2169 
2170 call vg6d_wind_unrot(volgrid6d_in)
2171 
2172 ntime=0
2173 ntimerange=0
2174 nlevel=0
2175 nvar=0
2176 nnetwork=1
2177 
2178 call get_val(this,time_definition=time_definition)
2179 if (.not. c_e(time_definition)) then
2180  time_definition=1 ! default to validity time
2181 endif
2182 
2183 IF (PRESENT(v7d)) THEN
2184  CALL vol7d_copy(v7d, v7d_locana)
2185 ELSE
2186  CALL init(v7d_locana)
2187 ENDIF
2189 if (associated(volgrid6d_in%timerange)) ntimerange=size(volgrid6d_in%timerange)
2190 
2191 if (associated(volgrid6d_in%time)) then
2192 
2193  ntime=size(volgrid6d_in%time)
2194 
2195  if (time_definition /= volgrid6d_in%time_definition) then
2196 
2197  ! converto reference in validity
2198  allocate (validitytime(ntime,ntimerange),stat=stallo)
2199  if (stallo /=0)then
2200  call l4f_category_log(volgrid6d_in%category,l4f_fatal,"allocating memory")
2201  call raise_fatal_error()
2202  end if
2203 
2204  do itime=1,ntime
2205  do itimerange=1,ntimerange
2206  if (time_definition > volgrid6d_in%time_definition) then
2207  validitytime(itime,itimerange) = &
2208  volgrid6d_in%time(itime) + timedelta_new(sec=volgrid6d_in%timerange(itimerange)%p1)
2209  else
2210  validitytime(itime,itimerange) = &
2211  volgrid6d_in%time(itime) - timedelta_new(sec=volgrid6d_in%timerange(itimerange)%p1)
2212  end if
2213  end do
2214  end do
2215 
2216  ntime = count_distinct(reshape(validitytime,(/ntime*ntimerange/)), back=.true.)
2217  deallocate (validitytime)
2218 
2219  end if
2220 end if
2221 
2222 
2223 if (associated(volgrid6d_in%level)) nlevel=size(volgrid6d_in%level)
2224 if (associated(volgrid6d_in%var)) nvar=size(volgrid6d_in%var)
2225 
2226 CALL init(grid_trans, this, volgrid6d_in%griddim, v7d_locana, &
2227  maskgrid=maskgrid, maskbounds=maskbounds, find_index=find_index, &
2228  categoryappend=categoryappend)
2229 CALL init (vol7d_out,time_definition=time_definition)
2230 
2231 IF (c_e(grid_trans)) THEN
2232 
2233  nana=SIZE(v7d_locana%ana)
2234  CALL vol7d_alloc(vol7d_out, nana=nana, ntime=ntime, nlevel=nlevel, &
2235  ntimerange=ntimerange, ndativarr=nvar, nnetwork=nnetwork)
2236  vol7d_out%ana = v7d_locana%ana
2237 
2238  CALL get_val(grid_trans, output_point_index=point_index)
2239  IF (ALLOCATED(point_index)) THEN
2240 ! check that size(point_index) == nana?
2241  CALL vol7d_alloc(vol7d_out, nanavari=1)
2242  CALL init(vol7d_out%anavar%i(1), 'B01192')
2243  ENDIF
2244 
2245  CALL vol7d_alloc_vol(vol7d_out)
2246 
2247  IF (ALLOCATED(point_index)) THEN
2248  DO inetwork = 1, nnetwork
2249  vol7d_out%volanai(:,1,inetwork) = point_index(:)
2250  ENDDO
2251  ENDIF
2252  CALL compute(grid_trans, volgrid6d_in, vol7d_out, networkname, noconvert)
2253 ELSE
2254  CALL l4f_log(l4f_error, 'vg6d_v7d_transform: transformation not valid')
2255  CALL raise_error()
2256 ENDIF
2257 
2258 CALL delete(grid_trans)
2259 
2260 #ifdef HAVE_DBALLE
2261 ! set variables to a conformal state
2262 CALL vol7d_dballe_set_var_du(vol7d_out)
2263 #endif
2264 
2265 CALL delete(v7d_locana)
2266 
2267 END SUBROUTINE volgrid6d_v7d_transform
2268 
2269 
2278 SUBROUTINE volgrid6dv_v7d_transform(this, volgrid6d_in, vol7d_out, v7d, &
2279  maskgrid, maskbounds, networkname, noconvert, find_index, categoryappend)
2280 TYPE(transform_def),INTENT(in) :: this
2281 TYPE(volgrid6d),INTENT(inout) :: volgrid6d_in(:)
2282 TYPE(vol7d),INTENT(out) :: vol7d_out
2283 TYPE(vol7d),INTENT(in),OPTIONAL :: v7d
2284 REAL,INTENT(in),OPTIONAL :: maskgrid(:,:)
2285 REAL,INTENT(in),OPTIONAL :: maskbounds(:)
2286 CHARACTER(len=*),OPTIONAL,INTENT(in) :: networkname
2287 LOGICAL,OPTIONAL,INTENT(in) :: noconvert
2288 PROCEDURE(basic_find_index),POINTER,OPTIONAL :: find_index
2289 CHARACTER(len=*),INTENT(in),OPTIONAL :: categoryappend
2290 
2291 integer :: i
2292 TYPE(vol7d) :: v7dtmp
2293 
2294 
2295 CALL init(v7dtmp)
2296 CALL init(vol7d_out)
2297 
2298 DO i=1,SIZE(volgrid6d_in)
2299  CALL transform(this, volgrid6d_in(i), v7dtmp, v7d=v7d, &
2300  maskgrid=maskgrid, maskbounds=maskbounds, &
2301  networkname=networkname, noconvert=noconvert, find_index=find_index, &
2302  categoryappend=categoryappend)
2303  CALL vol7d_append(vol7d_out, v7dtmp)
2304 ENDDO
2305 
2306 END SUBROUTINE volgrid6dv_v7d_transform
2307 
2308 
2309 ! Internal method for performing sparse point to grid computations
2310 SUBROUTINE v7d_volgrid6d_transform_compute(this, vol7d_in, volgrid6d_out, networkname, gaid_template)
2311 TYPE(grid_transform),INTENT(in) :: this ! object specifying the specific transformation
2312 type(vol7d), INTENT(in) :: vol7d_in ! object to be transformed
2313 type(volgrid6d), INTENT(inout) :: volgrid6d_out ! transformed object
2314 CHARACTER(len=*),OPTIONAL,INTENT(in) :: networkname ! select the network to be processed from the \a vol7d input object, default the first network
2315 TYPE(grid_id),OPTIONAL,INTENT(in) :: gaid_template ! the template (typically grib_api) to be associated with output data, it also helps in improving variable conversion
2316 
2317 integer :: nana, ntime, ntimerange, nlevel, nvar
2318 INTEGER :: ilevel, itime, itimerange, ivar, inetwork
2319 
2320 REAL,POINTER :: voldatiout(:,:,:)
2321 type(vol7d_network) :: network
2322 TYPE(conv_func), pointer :: c_func(:)
2323 !TODO category sarebbe da prendere da vol7d
2324 #ifdef DEBUG
2325 CALL l4f_category_log(volgrid6d_out%category, l4f_debug, &
2326  'start v7d_volgrid6d_transform_compute')
2327 #endif
2328 
2329 ntime=0
2330 ntimerange=0
2331 nlevel=0
2332 nvar=0
2333 
2334 IF (PRESENT(networkname)) THEN
2335  CALL init(network,name=networkname)
2336  inetwork = index(vol7d_in%network,network)
2337  IF (inetwork <= 0) THEN
2338  CALL l4f_category_log(volgrid6d_out%category,l4f_warn, &
2339  'network '//trim(networkname)//' not found, first network will be transformed')
2340  inetwork = 1
2341  ENDIF
2342 ELSE
2343  inetwork = 1
2344 ENDIF
2345 
2346 ! no time_definition conversion implemented, output will be the same as input
2347 if (associated(vol7d_in%time))then
2348  ntime=size(vol7d_in%time)
2349  volgrid6d_out%time=vol7d_in%time
2350 end if
2351 
2352 if (associated(vol7d_in%timerange))then
2353  ntimerange=size(vol7d_in%timerange)
2354  volgrid6d_out%timerange=vol7d_in%timerange
2355 end if
2356 
2357 if (associated(vol7d_in%level))then
2358  nlevel=size(vol7d_in%level)
2359  volgrid6d_out%level=vol7d_in%level
2360 end if
2361 
2362 if (associated(vol7d_in%dativar%r))then
2363  nvar=size(vol7d_in%dativar%r)
2364  CALL varbufr2vargrib(vol7d_in%dativar%r, volgrid6d_out%var, c_func, gaid_template)
2365 end if
2366 
2367 nana=SIZE(vol7d_in%voldatir, 1)
2368 ! allocate once for speed
2369 IF (.NOT.ASSOCIATED(volgrid6d_out%voldati)) THEN
2370  ALLOCATE(voldatiout(volgrid6d_out%griddim%dim%nx, volgrid6d_out%griddim%dim%ny, &
2371  nlevel))
2372 ENDIF
2373 
2374 DO ivar=1,nvar
2375  DO itimerange=1,ntimerange
2376  DO itime=1,ntime
2377 
2378 ! clone the gaid template where I have data
2379  IF (PRESENT(gaid_template)) THEN
2380  DO ilevel = 1, nlevel
2381  IF (any(c_e(vol7d_in%voldatir(:,itime,ilevel,itimerange,ivar,inetwork)))) THEN
2382  CALL copy(gaid_template, volgrid6d_out%gaid(ilevel,itime,itimerange,ivar))
2383  ELSE
2384  volgrid6d_out%gaid(ilevel,itime,itimerange,ivar) = grid_id_new()
2385  ENDIF
2386  ENDDO
2387  ENDIF
2388 
2389 ! get data
2390  IF (ASSOCIATED(volgrid6d_out%voldati)) & ! improve!!!!
2391  CALL volgrid_get_vol_3d(volgrid6d_out, itime, itimerange, ivar, &
2392  voldatiout)
2393 ! do the interpolation
2394  CALL compute(this, &
2395  vol7d_in%voldatir(:,itime,:,itimerange,ivar,inetwork), voldatiout, &
2396  vol7d_in%dativar%r(ivar))
2397 ! rescale valid data according to variable conversion table
2398  IF (ASSOCIATED(c_func)) THEN
2399  CALL compute(c_func(ivar), voldatiout(:,:,:))
2400  ENDIF
2401 ! put data
2402  CALL volgrid_set_vol_3d(volgrid6d_out, itime, itimerange, ivar, &
2403  voldatiout)
2404 
2405  ENDDO
2406  ENDDO
2407 ENDDO
2408 
2409 IF (.NOT.ASSOCIATED(volgrid6d_out%voldati)) THEN
2410  DEALLOCATE(voldatiout)
2411 ENDIF
2412 IF (ASSOCIATED(c_func)) THEN
2413  DEALLOCATE(c_func)
2414 ENDIF
2415 
2416 END SUBROUTINE v7d_volgrid6d_transform_compute
2417 
2418 
2425 SUBROUTINE v7d_volgrid6d_transform(this, griddim, vol7d_in, volgrid6d_out, &
2426  networkname, gaid_template, categoryappend)
2427 TYPE(transform_def),INTENT(in) :: this
2428 TYPE(griddim_def),INTENT(in),OPTIONAL :: griddim
2429 ! TODO ripristinare intent(in) dopo le opportune modifiche in grid_class.F90
2430 TYPE(vol7d),INTENT(inout) :: vol7d_in
2431 TYPE(volgrid6d),INTENT(out) :: volgrid6d_out
2432 CHARACTER(len=*),OPTIONAL,INTENT(in) :: networkname
2433 TYPE(grid_id),OPTIONAL,INTENT(in) :: gaid_template
2434 CHARACTER(len=*),INTENT(in),OPTIONAL :: categoryappend
2435 
2436 type(grid_transform) :: grid_trans
2437 integer :: ntime, ntimerange, nlevel, nvar
2438 
2439 
2440 !TODO la category sarebbe da prendere da vol7d
2441 !call l4f_category_log(vol7d_out%category,L4F_DEBUG,"start volgrid6d_transform")
2442 
2443 CALL vol7d_alloc_vol(vol7d_in) ! be safe
2444 ntime=SIZE(vol7d_in%time)
2445 ntimerange=SIZE(vol7d_in%timerange)
2446 nlevel=SIZE(vol7d_in%level)
2447 nvar=0
2448 if (associated(vol7d_in%dativar%r)) nvar=size(vol7d_in%dativar%r)
2449 
2450 IF (nvar <= 0) THEN ! use vol7d category once it will be implemented
2451  CALL l4f_log(l4f_error, &
2452  "trying to transform a vol7d object incomplete or without real variables")
2453  CALL init(volgrid6d_out) ! initialize to empty
2454  CALL raise_error()
2455  RETURN
2456 ENDIF
2457 
2458 CALL init(grid_trans, this, vol7d_in, griddim, categoryappend=categoryappend)
2459 CALL init(volgrid6d_out, griddim, time_definition=vol7d_in%time_definition, &
2460  categoryappend=categoryappend)
2461 
2462 IF (c_e(grid_trans)) THEN
2463 
2464  CALL volgrid6d_alloc(volgrid6d_out, griddim%dim, ntime=ntime, nlevel=nlevel, &
2465  ntimerange=ntimerange, nvar=nvar)
2466 ! can I avoid decode=.TRUE. here, using gaid_template?
2467  CALL volgrid6d_alloc_vol(volgrid6d_out, decode=.true.)
2468 
2469  CALL compute(grid_trans, vol7d_in, volgrid6d_out, networkname, gaid_template)
2470 
2471  CALL vg6d_wind_rot(volgrid6d_out)
2472 ELSE
2473 ! should log with grid_trans%category, but it is private
2474  CALL l4f_log(l4f_error, 'v7d_vg6d_transform: transformation not valid')
2475  CALL raise_error()
2476 ENDIF
2477 
2478 CALL delete(grid_trans)
2479 
2480 END SUBROUTINE v7d_volgrid6d_transform
2481 
2482 
2483 ! Internal method for performing sparse point to sparse point computations
2484 SUBROUTINE v7d_v7d_transform_compute(this, vol7d_in, vol7d_out, lev_out, &
2485  var_coord_vol)
2486 TYPE(grid_transform),INTENT(in) :: this ! oggetto di trasformazione per grigliato
2487 type(vol7d), INTENT(in) :: vol7d_in ! oggetto da trasformare
2488 type(vol7d), INTENT(inout) :: vol7d_out ! oggetto trasformato
2489 TYPE(vol7d_level),INTENT(in),OPTIONAL :: lev_out(:) ! vol7d_level object defining target vertical grid, for vertical interpolations
2490 INTEGER,INTENT(in),OPTIONAL :: var_coord_vol ! index of variable defining vertical coordinate values in input volume
2491 
2492 INTEGER :: itime, itimerange, ilevel, ivar, inetwork, &
2493  levshift, levused, lvar_coord_vol, spos
2494 REAL,ALLOCATABLE :: coord_3d_in(:,:,:)
2495 TYPE(vol7d_level) :: output_levtype
2496 
2497 lvar_coord_vol = optio_i(var_coord_vol)
2498 vol7d_out%time(:) = vol7d_in%time(:)
2499 vol7d_out%timerange(:) = vol7d_in%timerange(:)
2500 IF (PRESENT(lev_out)) THEN
2501  vol7d_out%level(:) = lev_out(:)
2502 ELSE
2503  vol7d_out%level(:) = vol7d_in%level(:)
2504 ENDIF
2505 vol7d_out%network(:) = vol7d_in%network(:)
2506 IF (ASSOCIATED(vol7d_in%dativar%r)) THEN ! work only when real vars are available
2507  vol7d_out%dativar%r(:) = vol7d_in%dativar%r(:)
2508 
2509  CALL get_val(this, levshift=levshift, levused=levused)
2510  spos = imiss
2511  IF (c_e(lvar_coord_vol)) THEN
2512  CALL get_val(this%trans, output_levtype=output_levtype)
2513  IF (output_levtype%level1 == 103 .OR. output_levtype%level1 == 108) THEN
2514  spos = firsttrue(vol7d_in%level(:) == vol7d_level_new(1))
2515  IF (spos == 0) THEN
2516  CALL l4f_log(l4f_error, &
2517  'output level '//t2c(output_levtype%level1)// &
2518  ' requested, but height/press of surface not provided in volume')
2519  ENDIF
2520  IF (.NOT.c_e(levshift) .AND. .NOT.c_e(levused)) THEN
2521  CALL l4f_log(l4f_error, &
2522  'internal inconsistence, levshift and levused undefined when they should be')
2523  ENDIF
2524  ALLOCATE(coord_3d_in(SIZE(vol7d_in%ana),1,SIZE(vol7d_in%level)))
2525  ENDIF
2526 
2527  ENDIF
2528 
2529  DO inetwork = 1, SIZE(vol7d_in%network)
2530  DO ivar = 1, SIZE(vol7d_in%dativar%r)
2531  DO itimerange = 1, SIZE(vol7d_in%timerange)
2532  DO itime = 1, SIZE(vol7d_in%time)
2533 
2534 ! dirty trick to make voldatir look like a 2d-array of shape (nana,1)
2535  IF (c_e(lvar_coord_vol)) THEN
2536  IF (c_e(spos)) THEN ! compute difference wrt surface coordinate
2537  IF (spos == 0) THEN ! error condition, set all to missing and goodnight
2538  coord_3d_in(:,:,levshift+1:levshift+levused) = rmiss
2539  ELSE
2540  DO ilevel = levshift+1, levshift+levused
2541  WHERE(c_e(vol7d_in%voldatir(:,itime:itime,ilevel,itimerange,lvar_coord_vol,inetwork)) .AND. &
2542  c_e(vol7d_in%voldatir(:,itime:itime,spos,itimerange,lvar_coord_vol,inetwork)))
2543  coord_3d_in(:,:,ilevel) = vol7d_in%voldatir(:,itime:itime,ilevel,itimerange,lvar_coord_vol,inetwork) - &
2544  vol7d_in%voldatir(:,itime:itime,spos,itimerange,lvar_coord_vol,inetwork)
2545  ELSEWHERE
2546  coord_3d_in(:,:,ilevel) = rmiss
2547  END WHERE
2548  ENDDO
2549  ENDIF
2550  CALL compute(this, &
2551  vol7d_in%voldatir(:,itime,:,itimerange,ivar,inetwork), &
2552  vol7d_out%voldatir(:,itime:itime,:,itimerange,ivar,inetwork), &
2553  var=vol7d_in%dativar%r(ivar), &
2554  coord_3d_in=coord_3d_in)
2555  ELSE
2556  CALL compute(this, &
2557  vol7d_in%voldatir(:,itime,:,itimerange,ivar,inetwork), &
2558  vol7d_out%voldatir(:,itime:itime,:,itimerange,ivar,inetwork), &
2559  var=vol7d_in%dativar%r(ivar), &
2560  coord_3d_in=vol7d_in%voldatir(:,itime:itime,:,itimerange, &
2561  lvar_coord_vol,inetwork))
2562  ENDIF
2563  ELSE
2564  CALL compute(this, &
2565  vol7d_in%voldatir(:,itime,:,itimerange,ivar,inetwork), &
2566  vol7d_out%voldatir(:,itime:itime,:,itimerange,ivar,inetwork), &
2567  var=vol7d_in%dativar%r(ivar))
2568  ENDIF
2569  ENDDO
2570  ENDDO
2571  ENDDO
2572  ENDDO
2573 
2574 ENDIF
2575 
2576 END SUBROUTINE v7d_v7d_transform_compute
2577 
2578 
2586 SUBROUTINE v7d_v7d_transform(this, vol7d_in, vol7d_out, v7d, maskbounds, &
2587  lev_out, vol7d_coord_in, categoryappend)
2588 TYPE(transform_def),INTENT(in) :: this
2589 TYPE(vol7d),INTENT(inout) :: vol7d_in
2590 TYPE(vol7d),INTENT(out) :: vol7d_out
2591 TYPE(vol7d),INTENT(in),OPTIONAL :: v7d
2592 REAL,INTENT(in),OPTIONAL :: maskbounds(:)
2593 TYPE(vol7d_level),INTENT(in),OPTIONAL,TARGET :: lev_out(:)
2594 TYPE(vol7d),INTENT(in),OPTIONAL :: vol7d_coord_in
2595 CHARACTER(len=*),INTENT(in),OPTIONAL :: categoryappend
2596 
2597 INTEGER :: nvar, inetwork
2598 TYPE(grid_transform) :: grid_trans
2599 TYPE(vol7d_level),POINTER :: llev_out(:)
2600 TYPE(vol7d_level) :: input_levtype, output_levtype
2601 TYPE(vol7d_var) :: vcoord_var
2602 REAL,ALLOCATABLE :: coord_3d_in(:,:,:)
2603 INTEGER :: var_coord_in, var_coord_vol, i, k, ulstart, ulend, spos
2604 INTEGER,ALLOCATABLE :: point_index(:)
2605 TYPE(vol7d) :: v7d_locana, vol7d_tmpana
2606 CHARACTER(len=80) :: trans_type
2607 LOGICAL,ALLOCATABLE :: mask_in(:), point_mask(:)
2608 
2609 CALL vol7d_alloc_vol(vol7d_in) ! be safe
2610 nvar=0
2611 IF (ASSOCIATED(vol7d_in%dativar%r)) nvar=SIZE(vol7d_in%dativar%r)
2612 
2613 CALL init(v7d_locana)
2614 IF (PRESENT(v7d)) v7d_locana = v7d
2615 CALL init(vol7d_out, time_definition=vol7d_in%time_definition)
2616 
2617 CALL get_val(this, trans_type=trans_type)
2618 
2619 var_coord_vol = imiss
2620 IF (trans_type == 'vertint') THEN
2621 
2622  IF (PRESENT(lev_out)) THEN
2623 
2624 ! if vol7d_coord_in provided and allocated, check that it fits
2625  var_coord_in = -1
2626  IF (PRESENT(vol7d_coord_in)) THEN
2627  IF (ASSOCIATED(vol7d_coord_in%voldatir) .AND. &
2628  ASSOCIATED(vol7d_coord_in%dativar%r)) THEN
2629 
2630 ! strictly 1 time, 1 timerange and 1 network
2631  IF (SIZE(vol7d_coord_in%voldatir,2) /= 1 .OR. &
2632  SIZE(vol7d_coord_in%voldatir,4) /= 1 .OR. &
2633  SIZE(vol7d_coord_in%voldatir,6) /= 1) THEN
2634  CALL l4f_log(l4f_error, &
2635  'volume providing constant input vertical coordinate must have &
2636  &only 1 time, 1 timerange and 1 network')
2637  CALL raise_error()
2638  RETURN
2639  ENDIF
2640 
2641 ! search for variable providing vertical coordinate
2642  CALL get_val(this, output_levtype=output_levtype)
2643  vcoord_var = vol7d_var_new(vol7d_level_to_var(output_levtype))
2644  IF (.NOT.c_e(vcoord_var)) THEN
2645  CALL l4f_log(l4f_error, &
2646  'requested output level type '//t2c(output_levtype%level1)// &
2647  ' does not correspond to any known physical variable for &
2648  &providing vertical coordinate')
2649  CALL raise_error()
2650  RETURN
2651  ENDIF
2652 
2653  var_coord_in = index(vol7d_coord_in%dativar%r, vcoord_var)
2654 
2655  IF (var_coord_in <= 0) THEN
2656  CALL l4f_log(l4f_error, &
2657  'volume providing constant input vertical coordinate contains no &
2658  &real variables matching output level type '//t2c(output_levtype%level1))
2659  CALL raise_error()
2660  RETURN
2661  ENDIF
2662  CALL l4f_log(l4f_info, &
2663  'Coordinate for vertint found in coord volume at position '// &
2664  t2c(var_coord_in))
2665 
2666 ! check vertical coordinate system
2667  CALL get_val(this, input_levtype=input_levtype)
2668  mask_in = & ! implicit allocation
2669  (vol7d_coord_in%level(:)%level1 == input_levtype%level1) .AND. &
2670  (vol7d_coord_in%level(:)%level2 == input_levtype%level2)
2671  ulstart = firsttrue(mask_in)
2672  ulend = lasttrue(mask_in)
2673  IF (ulstart == 0 .OR. ulend == 0) THEN
2674  CALL l4f_log(l4f_error, &
2675  'coordinate file does not contain levels of type '// &
2676  t2c(input_levtype%level1)//'/'//t2c(input_levtype%level2)// &
2677  ' specified for input data')
2678  CALL raise_error()
2679  RETURN
2680  ENDIF
2681 
2682  coord_3d_in = vol7d_coord_in%voldatir(:,1:1,ulstart:ulend,1,var_coord_in,1) ! dirty 1:1, implicit allocation
2683 ! special case
2684  IF (output_levtype%level1 == 103 &
2685  .OR. output_levtype%level1 == 108) THEN ! surface coordinate needed
2686  spos = firsttrue(vol7d_coord_in%level(:) == vol7d_level_new(1))
2687  IF (spos == 0) THEN
2688  CALL l4f_log(l4f_error, &
2689  'output level '//t2c(output_levtype%level1)// &
2690  ' requested, but height/press of surface not provided in coordinate file')
2691  CALL raise_error()
2692  RETURN
2693  ENDIF
2694  DO k = 1, SIZE(coord_3d_in,3)
2695  WHERE(c_e(coord_3d_in(:,:,k)) .AND. &
2696  c_e(vol7d_coord_in%voldatir(:,1:1,spos,1,var_coord_in,1)))
2697  coord_3d_in(:,:,k) = coord_3d_in(:,:,k) - &
2698  vol7d_coord_in%voldatir(:,1:1,spos,1,var_coord_in,1)
2699  ELSEWHERE
2700  coord_3d_in(:,:,k) = rmiss
2701  END WHERE
2702  ENDDO
2703  ENDIF
2704 
2705  ENDIF
2706  ENDIF
2707 
2708  IF (var_coord_in <= 0) THEN ! search for coordinate within volume
2709 ! search for variable providing vertical coordinate
2710  CALL get_val(this, output_levtype=output_levtype)
2711  vcoord_var = vol7d_var_new(vol7d_level_to_var(output_levtype))
2712  IF (c_e(vcoord_var)) THEN
2713  DO i = 1, SIZE(vol7d_in%dativar%r)
2714  IF (vol7d_in%dativar%r(i) == vcoord_var) THEN
2715  var_coord_vol = i
2716  EXIT
2717  ENDIF
2718  ENDDO
2719 
2720  IF (c_e(var_coord_vol)) THEN
2721  CALL l4f_log(l4f_info, &
2722  'Coordinate for vertint found in input volume at position '// &
2723  t2c(var_coord_vol))
2724  ENDIF
2725 
2726  ENDIF
2727  ENDIF
2728 
2729  IF (var_coord_in > 0) THEN
2730  CALL init(grid_trans, this, lev_in=vol7d_in%level, lev_out=lev_out, &
2731  coord_3d_in=coord_3d_in, categoryappend=categoryappend)
2732  ELSE
2733  CALL init(grid_trans, this, lev_in=vol7d_in%level, lev_out=lev_out, &
2734  categoryappend=categoryappend)
2735  ENDIF
2736 
2737  CALL get_val(grid_trans, output_level_auto=llev_out) ! get levels if auto-generated
2738  IF (.NOT.associated(llev_out)) llev_out => lev_out
2739 
2740  IF (c_e(grid_trans)) then! .AND. nvar > 0) THEN
2741 
2742  CALL vol7d_alloc(vol7d_out, nana=SIZE(vol7d_in%ana), &
2743  ntime=SIZE(vol7d_in%time), ntimerange=SIZE(vol7d_in%timerange), &
2744  nlevel=SIZE(llev_out), nnetwork=SIZE(vol7d_in%network), ndativarr=nvar)
2745  vol7d_out%ana(:) = vol7d_in%ana(:)
2746 
2747  CALL vol7d_alloc_vol(vol7d_out)
2748 
2749 ! no need to check c_e(var_coord_vol) here since the presence of
2750 ! this%coord_3d_in (external) has precedence over coord_3d_in internal
2751 ! in grid_transform_compute
2752  CALL compute(grid_trans, vol7d_in, vol7d_out, llev_out, &
2753  var_coord_vol=var_coord_vol)
2754  ELSE
2755  CALL l4f_log(l4f_error, 'v7d_v7d_transform: transformation not valid')
2756  CALL raise_error()
2757  ENDIF
2758  ELSE
2759  CALL l4f_log(l4f_error, &
2760  'v7d_v7d_transform: vertint requested but lev_out not provided')
2761  CALL raise_error()
2762  ENDIF
2763 
2764 ELSE
2765 
2766  CALL init(grid_trans, this, vol7d_in, v7d_locana, maskbounds=maskbounds, &
2767  categoryappend=categoryappend)
2768 ! if this init is successful, I am sure that v7d_locana%ana is associated
2769 
2770  IF (c_e(grid_trans)) then! .AND. nvar > 0) THEN
2771 
2772  CALL vol7d_alloc(vol7d_out, nana=SIZE(v7d_locana%ana), &
2773  ntime=SIZE(vol7d_in%time), ntimerange=SIZE(vol7d_in%timerange), &
2774  nlevel=SIZE(vol7d_in%level), nnetwork=SIZE(vol7d_in%network), ndativarr=nvar)
2775  vol7d_out%ana = v7d_locana%ana
2776 
2777  CALL get_val(grid_trans, point_mask=point_mask, output_point_index=point_index)
2778 
2779  IF (ALLOCATED(point_index)) THEN
2780  CALL vol7d_alloc(vol7d_out, nanavari=1)
2781  CALL init(vol7d_out%anavar%i(1), 'B01192')
2782  ENDIF
2783 
2784  CALL vol7d_alloc_vol(vol7d_out)
2785 
2786  IF (ALLOCATED(point_index)) THEN
2787  DO inetwork = 1, SIZE(vol7d_in%network)
2788  vol7d_out%volanai(:,1,inetwork) = point_index(:)
2789  ENDDO
2790  ENDIF
2791  CALL compute(grid_trans, vol7d_in, vol7d_out)
2792 
2793  IF (ALLOCATED(point_mask)) THEN ! keep full ana
2794  IF (SIZE(point_mask) /= SIZE(vol7d_in%ana)) THEN
2795  CALL l4f_log(l4f_warn, &
2796  'v7d_v7d_transform: inconsistency in point size: '//t2c(SIZE(point_mask)) &
2797  //':'//t2c(SIZE(vol7d_in%ana)))
2798  ELSE
2799 #ifdef DEBUG
2800  CALL l4f_log(l4f_debug, 'v7d_v7d_transform: merging ana from in to out')
2801 #endif
2802  CALL vol7d_copy(vol7d_in, vol7d_tmpana, &
2803  lana=point_mask, lnetwork=(/.true./), &
2804  ltime=(/.false./), ltimerange=(/.false./), llevel=(/.false./))
2805  CALL vol7d_append(vol7d_out, vol7d_tmpana)
2806  ENDIF
2807  ENDIF
2808 
2809  ELSE
2810  CALL l4f_log(l4f_error, 'v7d_v7d_transform: transformation not valid')
2811  CALL raise_error()
2812  ENDIF
2813 
2814 ENDIF
2815 
2816 CALL delete (grid_trans)
2817 IF (.NOT. PRESENT(v7d)) CALL delete(v7d_locana)
2818 
2819 END SUBROUTINE v7d_v7d_transform
2820 
2821 
2829 subroutine vg6d_wind_unrot(this)
2830 type(volgrid6d) :: this
2831 
2832 integer :: component_flag
2833 
2834 call get_val(this%griddim,component_flag=component_flag)
2835 
2836 if (component_flag == 1) then
2837  call l4f_category_log(this%category,l4f_info, &
2838  "unrotating vector components")
2839  call vg6d_wind__un_rot(this,.false.)
2840  call set_val(this%griddim,component_flag=0)
2841 else
2842  call l4f_category_log(this%category,l4f_info, &
2843  "no need to unrotate vector components")
2844 end if
2845 
2846 end subroutine vg6d_wind_unrot
2847 
2848 
2854 subroutine vg6d_wind_rot(this)
2855 type(volgrid6d) :: this
2856 
2857 integer :: component_flag
2858 
2859 call get_val(this%griddim,component_flag=component_flag)
2860 
2861 if (component_flag == 0) then
2862  call l4f_category_log(this%category,l4f_info, &
2863  "rotating vector components")
2864  call vg6d_wind__un_rot(this,.true.)
2865  call set_val(this%griddim,component_flag=1)
2866 else
2867  call l4f_category_log(this%category,l4f_info, &
2868  "no need to rotate vector components")
2869 end if
2870 
2871 end subroutine vg6d_wind_rot
2872 
2873 
2874 ! Generic UnRotate the wind components.
2875 SUBROUTINE vg6d_wind__un_rot(this,rot)
2876 TYPE(volgrid6d) :: this ! object containing wind to be (un)rotated
2877 LOGICAL :: rot ! if .true. rotate else unrotate
2878 
2879 INTEGER :: i, j, k, l, a11, a12, a21, a22, stallo
2880 double precision,pointer :: rot_mat(:,:,:)
2881 real,allocatable :: tmp_arr(:,:)
2882 REAL,POINTER :: voldatiu(:,:), voldativ(:,:)
2883 INTEGER,POINTER :: iu(:), iv(:)
2884 
2885 IF (.NOT.ASSOCIATED(this%var)) THEN
2886  CALL l4f_category_log(this%category, l4f_error, &
2887  "trying to unrotate an incomplete volgrid6d object")
2888  CALL raise_fatal_error()
2889 ! RETURN
2890 ENDIF
2891 
2892 CALL volgrid6d_var_hor_comp_index(this%var, iu, iv)
2893 IF (.NOT.ASSOCIATED(iu)) THEN
2894  CALL l4f_category_log(this%category,l4f_error, &
2895  "unrotation impossible")
2896  CALL raise_fatal_error()
2897 ! RETURN
2898 ENDIF
2899 
2900 ! Temporary workspace
2901 ALLOCATE(tmp_arr(this%griddim%dim%nx, this%griddim%dim%ny),stat=stallo)
2902 IF (stallo /= 0) THEN
2903  CALL l4f_category_log(this%category, l4f_fatal, "allocating memory")
2904  CALL raise_fatal_error()
2905 ENDIF
2906 ! allocate once for speed
2907 IF (.NOT.ASSOCIATED(this%voldati)) THEN
2908  ALLOCATE(voldatiu(this%griddim%dim%nx, this%griddim%dim%ny), &
2909  voldativ(this%griddim%dim%nx, this%griddim%dim%ny))
2910 ENDIF
2911 
2912 CALL griddim_unproj(this%griddim)
2913 CALL wind_unrot(this%griddim, rot_mat)
2914 
2915 a11=1
2916 if (rot)then
2917  a12=2
2918  a21=3
2919 else
2920  a12=3
2921  a21=2
2922 end if
2923 a22=4
2924 
2925 DO l = 1, SIZE(iu)
2926  DO k = 1, SIZE(this%timerange)
2927  DO j = 1, SIZE(this%time)
2928  DO i = 1, SIZE(this%level)
2929 ! get data
2930  CALL volgrid_get_vol_2d(this, i, j, k, iu(l), voldatiu)
2931  CALL volgrid_get_vol_2d(this, i, j, k, iv(l), voldativ)
2932 ! convert units forward
2933 ! CALL compute(conv_fwd(iu(l)), voldatiu)
2934 ! CALL compute(conv_fwd(iv(l)), voldativ)
2935 
2936 ! multiply wind components by rotation matrix
2937  WHERE(voldatiu /= rmiss .AND. voldativ /= rmiss)
2938  tmp_arr(:,:) = real(voldatiu(:,:)*rot_mat(:,:,a11) + &
2939  voldativ(:,:)*rot_mat(:,:,a12))
2940  voldativ(:,:) = real(voldatiu(:,:)*rot_mat(:,:,a21) + &
2941  voldativ(:,:)*rot_mat(:,:,a22))
2942  voldatiu(:,:) = tmp_arr(:,:)
2943  END WHERE
2944 ! convert units backward
2945 ! CALL uncompute(conv_fwd(iu(l)), voldatiu)
2946 ! CALL uncompute(conv_fwd(iv(l)), voldativ)
2947 ! put data
2948  CALL volgrid_set_vol_2d(this, i, j, k, iu(l), voldatiu)
2949  CALL volgrid_set_vol_2d(this, i, j, k, iv(l), voldativ)
2950  ENDDO
2951  ENDDO
2952  ENDDO
2953 ENDDO
2954 
2955 IF (.NOT.ASSOCIATED(this%voldati)) THEN
2956  DEALLOCATE(voldatiu, voldativ)
2957 ENDIF
2958 DEALLOCATE(rot_mat, tmp_arr, iu, iv)
2959 
2960 END SUBROUTINE vg6d_wind__un_rot
2961 
2962 
2963 !!$ try to understand the problem:
2964 !!$
2965 !!$ case:
2966 !!$
2967 !!$ 1) we have only one volume: we have to provide the direction of shift
2968 !!$ compute H and traslate on it
2969 !!$ 2) we have two volumes:
2970 !!$ 1) volume U and volume V: compute H and traslate on it
2971 !!$ 2) volume U/V and volume H : translate U/V on H
2972 !!$ 3) we have tree volumes: translate U and V on H
2973 !!$
2974 !!$ strange cases:
2975 !!$ 1) do not have U in volume U
2976 !!$ 2) do not have V in volume V
2977 !!$ 3) we have others variables more than U and V in volumes U e V
2978 !!$
2979 !!$
2980 !!$ so the steps are:
2981 !!$ 1) find the volumes
2982 !!$ 2) define or compute H grid
2983 !!$ 3) trasform the volumes in H
2984 
2985 !!$ N.B.
2986 !!$ case 1) for only one vg6d (U or V) is not managed, but
2987 !!$ the not pubblic subroutines will work but you have to know what you want to do
2988 
2989 
3006 subroutine vg6d_c2a (this)
3007 
3008 TYPE(volgrid6d),INTENT(inout) :: this(:)
3009 
3010 integer :: ngrid,igrid,jgrid,ugrid,vgrid,tgrid
3011 doubleprecision :: xmin, xmax, ymin, ymax
3012 doubleprecision :: xmin_t, xmax_t, ymin_t, ymax_t
3013 doubleprecision :: step_lon_t,step_lat_t
3014 character(len=80) :: type_t,type
3015 TYPE(griddim_def):: griddim_t
3016 
3017 ngrid=size(this)
3018 
3019 do igrid=1,ngrid
3020 
3021  call init(griddim_t)
3022 
3023  call get_val(this(igrid)%griddim,xmin=xmin_t, xmax=xmax_t, ymin=ymin_t, ymax=ymax_t,proj_type=type_t)
3024  step_lon_t=(xmax_t-xmin_t)/dble(this(igrid)%griddim%dim%nx-1)
3025  step_lat_t=(ymax_t-ymin_t)/dble(this(igrid)%griddim%dim%ny-1)
3026 
3027  do jgrid=1,ngrid
3029  ugrid=imiss
3030  vgrid=imiss
3031  tgrid=imiss
3032 
3033 #ifdef DEBUG
3034  call l4f_category_log(this(igrid)%category,l4f_debug,"C grid: search U/V/T points:"//to_char(igrid)//to_char(jgrid))
3035  call l4f_category_log(this(igrid)%category,l4f_debug,"C grid: test delta: "//to_char(step_lon_t)//to_char(step_lat_t))
3036 #endif
3037 
3038  if (this(igrid)%griddim == this(jgrid)%griddim ) cycle
3039 
3040  if (this(igrid)%griddim%dim%nx == this(jgrid)%griddim%dim%nx .and. &
3041  this(igrid)%griddim%dim%ny == this(jgrid)%griddim%dim%ny ) then
3042 
3043  call get_val(this(jgrid)%griddim,xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,proj_type=type)
3044 
3045  if (type_t /= type )cycle
3046 
3047 #ifdef DEBUG
3048  call l4f_category_log(this(igrid)%category,l4f_debug,"C grid: test U "//&
3049  to_char(xmin)//to_char(xmax)//to_char(ymin)//to_char(ymax))
3050 
3051  call l4f_category_log(this(igrid)%category,l4f_debug,"diff coordinate lon"//&
3052  to_char(abs(xmin - (xmin_t+step_lon_t/2.d0)))//&
3053  to_char(abs(xmax - (xmax_t+step_lon_t/2.d0))))
3054  call l4f_category_log(this(igrid)%category,l4f_debug,"diff coordinate lat"//&
3055  to_char(abs(ymin - (ymin_t+step_lat_t/2.d0)))//&
3056  to_char(abs(ymax - (ymax_t+step_lat_t/2.d0))))
3057 #endif
3058 
3059  if ( abs(xmin - (xmin_t+step_lon_t/2.d0)) < 1.d-3 .and. abs(xmax - (xmax_t+step_lon_t/2.d0)) < 1.d-3 ) then
3060  if ( abs(ymin - ymin_t) < 1.d-3 .and. abs(ymax - ymax_t) < 1.d-3 ) then
3061 
3062 #ifdef DEBUG
3063  call l4f_category_log(this(igrid)%category,l4f_debug,"C grid: found U")
3064 #endif
3065  ugrid=jgrid
3066  tgrid=igrid
3067 
3068  end if
3069  end if
3070 
3071 #ifdef DEBUG
3072  call l4f_category_log(this(igrid)%category,l4f_debug,"C grid: test V "//&
3073  to_char(xmin)//to_char(xmax)//to_char(ymin)//to_char(ymax))
3074 #endif
3075 
3076  if ( abs(ymin - (ymin_t+step_lat_t/2.d0)) < 1.d-3 .and. abs(ymax - (ymax_t+step_lat_t/2.d0)) < 1.d-3 ) then
3077  if ( abs(xmin - xmin_t) < 1.d-3 .and. abs(xmax - xmax_t) < 1.d-3 ) then
3078 
3079 #ifdef DEBUG
3080  call l4f_category_log(this(igrid)%category,l4f_debug,"C grid: found V")
3081 #endif
3082  vgrid=jgrid
3083  tgrid=igrid
3084 
3085  end if
3086  end if
3087 
3088 
3089  ! test if we have U and V
3090 
3091 #ifdef DEBUG
3092  call l4f_category_log(this(igrid)%category,l4f_debug,"C grid: test U and V"//&
3093  to_char(xmin_t)//to_char(xmax_t)//to_char(ymin_t)//to_char(ymax_t)//&
3094  to_char(xmin)//to_char(xmax)//to_char(ymin)//to_char(ymax))
3095 
3096  call l4f_category_log(this(igrid)%category,l4f_debug,"UV diff coordinate lon"//&
3097  to_char(abs(xmin_t - xmin)-step_lon_t/2.d0)//&
3098  to_char(abs(xmax_t - xmax)-step_lon_t/2.d0))
3099  call l4f_category_log(this(igrid)%category,l4f_debug,"UV diff coordinate lat"//&
3100  to_char(abs(ymin_t - ymin) -step_lat_t/2.d0)//&
3101  to_char(abs(ymax_t - ymax)-step_lat_t/2.d0))
3102 #endif
3103 
3104  if ( abs(ymin - (ymin_t+step_lat_t/2.d0)) < 2.d-3 .and. abs(ymax - (ymax_t+step_lat_t/2.d0)) < 2.d-3 ) then
3105  if ( abs(xmin_t - (xmin+step_lon_t/2.d0)) < 2.d-3 .and. abs(xmax_t - (xmax+step_lon_t/2.d0)) < 2.d-3 ) then
3106 
3107 #ifdef DEBUG
3108  call l4f_category_log(this(igrid)%category,l4f_debug,"C grid: found U and V case up and right")
3109 #endif
3110 
3111  vgrid=jgrid
3112  ugrid=igrid
3113 
3114  call init(griddim_t,xmin=xmin, xmax=xmax, ymin=ymin_t, ymax=ymax_t)
3115 
3116  end if
3117  end if
3118  end if
3119 
3120  ! abbiamo almeno due volumi: riportiamo U e/o V su T
3121  if (c_e(ugrid)) then
3122 #ifdef DEBUG
3123  call l4f_category_log(this(igrid)%category,l4f_debug,"C grid U points: interpolate U on T "//to_char(tgrid)//to_char(ugrid))
3124 #endif
3125  if (c_e(tgrid))then
3126  call vg6d_c2a_grid(this(ugrid),this(tgrid)%griddim,cgrid=1)
3127  else
3128  call vg6d_c2a_grid(this(ugrid),griddim_t,cgrid=1)
3129  end if
3130  call vg6d_c2a_mat(this(ugrid),cgrid=1)
3131  end if
3132 
3133  if (c_e(vgrid)) then
3134 #ifdef DEBUG
3135  call l4f_category_log(this(igrid)%category,l4f_debug,"C grid V points: interpolate V on T "//to_char(tgrid)//to_char(vgrid))
3136 #endif
3137  if (c_e(tgrid))then
3138  call vg6d_c2a_grid(this(vgrid),this(tgrid)%griddim,cgrid=2)
3139  else
3140  call vg6d_c2a_grid(this(vgrid),griddim_t,cgrid=2)
3141  end if
3142  call vg6d_c2a_mat(this(vgrid),cgrid=2)
3143  end if
3144 
3145  end do
3146 
3147  call delete(griddim_t)
3148 
3149 end do
3150 
3151 
3152 end subroutine vg6d_c2a
3153 
3154 
3155 ! Convert C grid to A grid
3156 subroutine vg6d_c2a_grid(this,griddim_t,cgrid)
3157 
3158 type(volgrid6d),intent(inout) :: this ! object containing fields to be translated (U or V points)
3159 type(griddim_def),intent(in),optional :: griddim_t ! object containing grid of T points
3160 integer,intent(in) :: cgrid ! in C grid (Arakawa) we have 0=T,1=U,2=V points
3161 
3162 doubleprecision :: xmin, xmax, ymin, ymax
3163 doubleprecision :: step_lon,step_lat
3164 
3165 
3166 if (present(griddim_t)) then
3167 
3168  call get_val(griddim_t,xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
3169  call set_val(this%griddim,xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax)
3170 ! improve grid definition precision
3171  CALL griddim_setsteps(this%griddim)
3172 
3173 else
3174 
3175  select case (cgrid)
3176 
3177  case(0)
3178 
3179 #ifdef DEBUG
3180  call l4f_category_log(this%category,l4f_debug,"C grid: T points, nothing to do")
3181 #endif
3182  return
3183 
3184  case (1)
3185 
3186 #ifdef DEBUG
3187  call l4f_category_log(this%category,l4f_debug,"C grid: U points, we need interpolation")
3188 #endif
3189 
3190  call get_val(this%griddim, xmin=xmin, xmax=xmax)
3191  step_lon=(xmax-xmin)/dble(this%griddim%dim%nx-1)
3192  xmin=xmin-step_lon/2.d0
3193  xmax=xmax-step_lon/2.d0
3194  call set_val(this%griddim, xmin=xmin, xmax=xmax)
3195 ! improve grid definition precision
3196  CALL griddim_setsteps(this%griddim)
3197 
3198  case (2)
3199 
3200 #ifdef DEBUG
3201  call l4f_category_log(this%category,l4f_debug,"C grid: V points, we need interpolation")
3202 #endif
3203 
3204  call get_val(this%griddim, ymin=ymin, ymax=ymax)
3205  step_lat=(ymax-ymin)/dble(this%griddim%dim%ny-1)
3206  ymin=ymin-step_lat/2.d0
3207  ymax=ymax-step_lat/2.d0
3208  call set_val(this%griddim, ymin=ymin, ymax=ymax)
3209 ! improve grid definition precision
3210  CALL griddim_setsteps(this%griddim)
3211 
3212  case default
3213 
3214  call l4f_category_log(this%category,l4f_fatal,"C grid type not known")
3215  call raise_fatal_error ()
3216 
3217  end select
3218 
3219 end if
3220 
3221 
3222 call griddim_unproj(this%griddim)
3223 
3224 
3225 end subroutine vg6d_c2a_grid
3226 
3227 ! Convert C grid to A grid
3228 subroutine vg6d_c2a_mat(this,cgrid)
3229 
3230 type(volgrid6d),intent(inout) :: this ! object containing fields to be translated
3231 integer,intent(in) :: cgrid ! in C grid (Arakawa) we have 0=T,1=U,2=V points
3232 
3233 INTEGER :: i, j, k, iv, stallo
3234 REAL,ALLOCATABLE :: tmp_arr(:,:)
3235 REAL,POINTER :: voldatiuv(:,:)
3236 
3237 
3238 IF (cgrid == 0) RETURN ! nothing to do
3239 IF (cgrid /= 1 .AND. cgrid /= 2) THEN ! wrong cgrid
3240  CALL l4f_category_log(this%category,l4f_fatal,"C grid type "// &
3241  trim(to_char(cgrid))//" not known")
3242  CALL raise_error()
3243  RETURN
3244 ENDIF
3245 
3246 ! Temporary workspace
3247 ALLOCATE(tmp_arr(this%griddim%dim%nx, this%griddim%dim%ny),stat=stallo)
3248 if (stallo /=0)then
3249  call l4f_log(l4f_fatal,"allocating memory")
3250  call raise_fatal_error()
3251 end if
3252 
3253 ! allocate once for speed
3254 IF (.NOT.ASSOCIATED(this%voldati)) THEN
3255  ALLOCATE(voldatiuv(this%griddim%dim%nx, this%griddim%dim%ny), stat=stallo)
3256  IF (stallo /= 0) THEN
3257  CALL l4f_log(l4f_fatal,"allocating memory")
3258  CALL raise_fatal_error()
3259  ENDIF
3260 ENDIF
3261 
3262 IF (cgrid == 1) THEN ! U points to H points
3263  DO iv = 1, SIZE(this%var)
3264  DO k = 1, SIZE(this%timerange)
3265  DO j = 1, SIZE(this%time)
3266  DO i = 1, SIZE(this%level)
3267  tmp_arr(:,:) = rmiss
3268  CALL volgrid_get_vol_2d(this, i, j, k, iv, voldatiuv)
3269 
3270 ! West boundary extrapolation
3271  WHERE(voldatiuv(1,:) /= rmiss .AND. voldatiuv(2,:) /= rmiss)
3272  tmp_arr(1,:) = voldatiuv(1,:) - (voldatiuv(2,:) - voldatiuv(1,:)) / 2.
3273  END WHERE
3274 
3275 ! Rest of the field
3276  WHERE(voldatiuv(1:this%griddim%dim%nx-1,:) /= rmiss .AND. &
3277  voldatiuv(2:this%griddim%dim%nx,:) /= rmiss)
3278  tmp_arr(2:this%griddim%dim%nx,:) = &
3279  (voldatiuv(1:this%griddim%dim%nx-1,:) + &
3280  voldatiuv(2:this%griddim%dim%nx,:)) / 2.
3281  END WHERE
3282 
3283  voldatiuv(:,:) = tmp_arr
3284  CALL volgrid_set_vol_2d(this, i, j, k, iv, voldatiuv)
3285  ENDDO
3286  ENDDO
3287  ENDDO
3288  ENDDO
3289 
3290 ELSE IF (cgrid == 2) THEN ! V points to H points
3291  DO iv = 1, SIZE(this%var)
3292  DO k = 1, SIZE(this%timerange)
3293  DO j = 1, SIZE(this%time)
3294  DO i = 1, SIZE(this%level)
3295  tmp_arr(:,:) = rmiss
3296  CALL volgrid_get_vol_2d(this, i, j, k, iv, voldatiuv)
3297 
3298 ! South boundary extrapolation
3299  WHERE(voldatiuv(:,1) /= rmiss .AND. voldatiuv(:,2) /= rmiss)
3300  tmp_arr(:,1) = voldatiuv(:,1) - (voldatiuv(:,2) - voldatiuv(:,1)) / 2.
3301  END WHERE
3302 
3303 ! Rest of the field
3304  WHERE(voldatiuv(:,1:this%griddim%dim%ny-1) /= rmiss .AND. &
3305  voldatiuv(:,2:this%griddim%dim%ny) /= rmiss)
3306  tmp_arr(:,2:this%griddim%dim%ny) = &
3307  (voldatiuv(:,1:this%griddim%dim%ny-1) + &
3308  voldatiuv(:,2:this%griddim%dim%ny)) / 2.
3309  END WHERE
3310 
3311  voldatiuv(:,:) = tmp_arr
3312  CALL volgrid_set_vol_2d(this, i, j, k, iv, voldatiuv)
3313  ENDDO
3314  ENDDO
3315  ENDDO
3316  ENDDO
3317 ENDIF ! tertium non datur
3318 
3319 IF (.NOT.ASSOCIATED(this%voldati)) THEN
3320  DEALLOCATE(voldatiuv)
3321 ENDIF
3322 DEALLOCATE (tmp_arr)
3323 
3324 end subroutine vg6d_c2a_mat
3325 
3326 
3330 subroutine display_volgrid6d (this)
3331 
3332 TYPE(volgrid6d),intent(in) :: this
3333 integer :: i
3334 
3335 #ifdef DEBUG
3336 call l4f_category_log(this%category,l4f_debug,"ora mostro gridinfo " )
3337 #endif
3338 
3339 print*,"----------------------- volgrid6d display ---------------------"
3340 call display(this%griddim)
3341 
3342 IF (ASSOCIATED(this%time))then
3343  print*,"---- time vector ----"
3344  print*,"elements=",size(this%time)
3345  do i=1, size(this%time)
3346  call display(this%time(i))
3347  end do
3348 end IF
3349 
3350 IF (ASSOCIATED(this%timerange))then
3351  print*,"---- timerange vector ----"
3352  print*,"elements=",size(this%timerange)
3353  do i=1, size(this%timerange)
3354  call display(this%timerange(i))
3355  end do
3356 end IF
3357 
3358 IF (ASSOCIATED(this%level))then
3359  print*,"---- level vector ----"
3360  print*,"elements=",size(this%level)
3361  do i=1, size(this%level)
3362  call display(this%level(i))
3363  end do
3364 end IF
3365 
3366 IF (ASSOCIATED(this%var))then
3367  print*,"---- var vector ----"
3368  print*,"elements=",size(this%var)
3369  do i=1, size(this%var)
3370  call display(this%var(i))
3371  end do
3372 end IF
3373 
3374 IF (ASSOCIATED(this%gaid))then
3375  print*,"---- gaid vector (present mask only) ----"
3376  print*,"elements=",shape(this%gaid)
3377  print*,c_e(reshape(this%gaid,(/SIZE(this%gaid)/)))
3378 end IF
3379 
3380 print*,"--------------------------------------------------------------"
3381 
3382 
3383 end subroutine display_volgrid6d
3384 
3385 
3389 subroutine display_volgrid6dv (this)
3390 
3391 TYPE(volgrid6d),intent(in) :: this(:)
3392 integer :: i
3393 
3394 print*,"----------------------- volgrid6d vector ---------------------"
3395 
3396 print*,"elements=",size(this)
3397 
3398 do i=1, size(this)
3399 
3400 #ifdef DEBUG
3401  call l4f_category_log(this(i)%category,l4f_debug,"ora mostro il vettore volgrid6d" )
3402 #endif
3403 
3404  call display(this(i))
3405 
3406 end do
3407 print*,"--------------------------------------------------------------"
3408 
3409 end subroutine display_volgrid6dv
3410 
3411 
3414 subroutine vg6dv_rounding(vg6din,vg6dout,level,timerange,nostatproc,merge)
3415 type(volgrid6d),intent(in) :: vg6din(:)
3416 type(volgrid6d),intent(out),pointer :: vg6dout(:)
3417 type(vol7d_level),intent(in),optional :: level(:)
3418 type(vol7d_timerange),intent(in),optional :: timerange(:)
3419 logical,intent(in),optional :: merge
3420 logical,intent(in),optional :: nostatproc
3421 
3422 integer :: i
3423 
3424 allocate(vg6dout(size(vg6din)))
3425 
3426 do i = 1, size(vg6din)
3427  call vg6d_rounding(vg6din(i),vg6dout(i),level,timerange,nostatproc,merge)
3428 end do
3429 
3430 end subroutine vg6dv_rounding
3431 
3443 subroutine vg6d_rounding(vg6din,vg6dout,level,timerange,nostatproc,merge)
3444 type(volgrid6d),intent(in) :: vg6din
3445 type(volgrid6d),intent(out) :: vg6dout
3446 type(vol7d_level),intent(in),optional :: level(:)
3447 type(vol7d_timerange),intent(in),optional :: timerange(:)
3448 logical,intent(in),optional :: merge
3450 logical,intent(in),optional :: nostatproc
3451 
3452 integer :: ilevel,itimerange
3453 type(vol7d_level) :: roundlevel(size(vg6din%level))
3454 type(vol7d_timerange) :: roundtimerange(size(vg6din%timerange))
3455 
3456 roundlevel=vg6din%level
3457 
3458 if (present(level))then
3459  do ilevel = 1, size(vg6din%level)
3460  if ((any(vg6din%level(ilevel) .almosteq. level))) then
3461  roundlevel(ilevel)=level(1)
3462  end if
3463  end do
3464 end if
3465 
3466 roundtimerange=vg6din%timerange
3467 
3468 if (present(timerange))then
3469  do itimerange = 1, size(vg6din%timerange)
3470  if ((any(vg6din%timerange(itimerange) .almosteq. timerange))) then
3471  roundtimerange(itimerange)=timerange(1)
3472  end if
3473  end do
3474 end if
3475 
3476 !set istantaneous values everywere
3477 !preserve p1 for forecast time
3478 if (optio_log(nostatproc)) then
3479  roundtimerange(:)%timerange=254
3480  roundtimerange(:)%p2=0
3481 end if
3482 
3483 
3484 call vg6d_reduce(vg6din,vg6dout,roundlevel,roundtimerange,merge)
3485 
3486 end subroutine vg6d_rounding
3487 
3496 subroutine vg6d_reduce(vg6din,vg6dout,roundlevel,roundtimerange,merge)
3497 type(volgrid6d),intent(in) :: vg6din
3498 type(volgrid6d),intent(out) :: vg6dout
3499 type(vol7d_level),intent(in) :: roundlevel(:)
3500 type(vol7d_timerange),intent(in) :: roundtimerange(:)
3501 logical,intent(in),optional :: merge
3502 
3503 integer :: nlevel,ntime,ntimerange,nvar,ilevel,itimerange,ivar,indl,indt,itime,nx,ny
3504 real,allocatable :: vol2d(:,:)
3505 
3506 nx=vg6din%griddim%dim%nx
3507 ny=vg6din%griddim%dim%ny
3508 nlevel=count_distinct(roundlevel,back=.true.)
3509 ntime=size(vg6din%time)
3510 ntimerange=count_distinct(roundtimerange,back=.true.)
3511 nvar=size(vg6din%var)
3512 
3513 call init(vg6dout, vg6din%griddim, vg6din%time_definition, categoryappend="generated by vg6d_reduce")
3514 call volgrid6d_alloc(vg6dout, vg6din%griddim%dim, ntime, nlevel, ntimerange, nvar)
3515 
3516 if ( ASSOCIATED(vg6din%voldati) .or. optio_log(merge)) then
3517  call volgrid6d_alloc_vol(vg6dout,inivol=.true.,decode=.true.)
3518  allocate(vol2d(nx,ny))
3519 else
3520  call volgrid6d_alloc_vol(vg6dout,inivol=.true.,decode=.false.)
3521 end if
3522 
3523 vg6dout%time=vg6din%time
3524 vg6dout%var=vg6din%var
3525 vg6dout%timerange=pack_distinct(roundtimerange,ntimerange,back=.true.)
3526 vg6dout%level=pack_distinct(roundlevel,nlevel,back=.true.)
3527 ! sort modified dimensions
3528 CALL sort(vg6dout%timerange)
3529 CALL sort(vg6dout%level)
3530 
3531 do ilevel=1,size(vg6din%level)
3532  indl=index(vg6dout%level,roundlevel(ilevel))
3533  do itimerange=1,size(vg6din%timerange)
3534  indt=index(vg6dout%timerange,roundtimerange(itimerange))
3535  do ivar=1, nvar
3536  do itime=1,ntime
3537 
3538  if ( ASSOCIATED(vg6din%voldati)) then
3539  vol2d=vg6din%voldati(:,:,ilevel,itime,itimerange,ivar)
3540  end if
3541 
3542  if (optio_log(merge)) then
3543 
3544  if ( .not. ASSOCIATED(vg6din%voldati)) then
3545  CALL grid_id_decode_data(vg6din%gaid(ilevel,itime,itimerange,ivar), vol2d)
3546  end if
3547 
3548  !! merge present data point by point
3549  where (.not. c_e(vg6dout%voldati(:,:,indl,itime,indt,ivar)))
3550 
3551  vg6dout%voldati(:,:,indl,itime,indt,ivar)=vol2d
3552 
3553  end where
3554  else if ( ASSOCIATED(vg6din%voldati)) then
3555  if (.not. any(c_e(vg6dout%voldati(:,:,indl,itime,indt,ivar))))then
3556  vg6dout%voldati(:,:,indl,itime,indt,ivar)=vol2d
3557  end if
3558  end if
3559 
3560  if (c_e(vg6din%gaid(ilevel,itime,itimerange,ivar)).and. .not. c_e(vg6dout%gaid(indl,itime,indt,ivar)))then
3561  call copy (vg6din%gaid(ilevel,itime,itimerange,ivar), vg6dout%gaid(indl,itime,indt,ivar))
3562  end if
3563  end do
3564  end do
3565  end do
3566 end do
3568 if ( ASSOCIATED(vg6din%voldati) .or. optio_log(merge)) then
3569  deallocate(vol2d)
3570 end if
3571 
3572 end subroutine vg6d_reduce
3573 
3574 
3575 end module volgrid6d_class
3576 
3577 
3578 
3583 
3590 
3593 
3596 
3599 
Write the object on a formatted or unformatted file.
Read the object from a formatted or unformatted file.
Functions that return a trimmed CHARACTER representation of the input variable.
Compute forward coordinate transformation from geographical system to projected system.
Represent level object in a pretty string.
Constructor, it creates a new instance of the object.
Operatore di valore assoluto di un intervallo.
Module for quickly interpreting the OPTIONAL parameters passed to a subprogram.
copy object
Destructor, it releases every information and memory buffer associated with the object.
Object describing a rectangular, homogeneous gridded dataset.
Transform between any combination of volgrid6d and vol7d objects by means of a transform_def object d...
This module defines an abstract interface to different drivers for access to files containing gridded...
Apply the conversion function this to values.
Module for describing geographically referenced regular grids.
Definition: grid_class.F90:247
Decode and return the data array from a grid_id object associated to a gridinfo object.
Encode a data array into a grid_id object associated to a gridinfo object.
Classi per la gestione delle coordinate temporali.
This module defines objects and methods for managing data volumes on rectangular georeferenced grids...
classe per import ed export di volumi da e in DB-All.e
Convert a level type to a physical variable.
Definisce l&#39;intervallo temporale di un&#39;osservazione meteo.
Method for returning the contents of the object.
Import an object dirctly from a native file, from a gridinfo object or from a supported file format t...
Export an object dirctly to a native file, to a gridinfo object or to a supported file format through...
Index method.
Classe per la gestione dei livelli verticali in osservazioni meteo e affini.
Classe per la gestione di un volume completo di dati osservati.
This module defines usefull general purpose function and subroutine.
Class for managing information about a single gridded georeferenced field, typically imported from an...
Definisce il livello verticale di un&#39;osservazione.
Classe per la gestione degli intervalli temporali di osservazioni meteo e affini. ...
Display on standard output a description of the volgrid6d object provided.
Module for defining the extension and coordinates of a rectangular georeferenced grid.
Clone the object, creating a new independent instance of the object exactly equal to the starting one...
classe per la gestione del logging
Class for managing physical variables in a grib 1/2 fashion.
Method for inserting elements of the array at a desired position.
Module for defining transformations between rectangular georeferenced grids and between grids and spa...
Method for setting the contents of the object.
Emit log message for a category with specific priority.
Reduce some dimensions (level and timerage) for semplification (rounding).

Generated with Doxygen.