15 use datetime_mod,
only: datetime, datetime_set, datetime_to_string, &
16 datetime_create, datetime_diff
17 use duration_mod,
only: duration, duration_to_string
18 use fckit_configuration_module,
only: fckit_configuration
19 use fckit_mpi_module,
only: fckit_mpi_min, fckit_mpi_max, fckit_mpi_sum
20 use kinds,
only: kind_real
21 use oops_variables_mod,
only: oops_variables
22 use tools_const,
only: deg2rad
25 use fms_io_mod,
only: fms_io_init, fms_io_exit, register_restart_field, &
26 restart_file_type, restore_state, free_restart_type, save_restart
27 use fms_mod,
only: write_data, set_domain
28 use horiz_interp_mod,
only : horiz_interp_type
29 use horiz_interp_spherical_mod,
only : horiz_interp_spherical, horiz_interp_spherical_del, &
30 horiz_interp_spherical_new
31 use mom_remapping,
only : remapping_cs, initialize_remapping, remapping_core_h, &
33 use mpp_domains_mod,
only : mpp_update_domains
57 character(len=:),
allocatable :: name
63 real(kind=kind_real),
allocatable :: val(:,:,:)
68 real(kind=kind_real),
pointer :: mask(:,:) => null()
73 real(kind=kind_real),
pointer :: lon(:,:) => null()
78 real(kind=kind_real),
pointer :: lat(:,:) => null()
88 procedure :: copy => soca_field_copy
91 procedure :: delete => soca_field_delete
94 procedure :: check_congruent => soca_field_check_congruent
97 procedure :: update_halo => soca_field_update_halo
100 procedure :: stencil_interp => soca_field_stencil_interp
124 procedure :: create => soca_fields_create
127 procedure :: copy => soca_fields_copy
130 procedure :: delete => soca_fields_delete
138 procedure :: get => soca_fields_get
141 procedure :: has => soca_fields_has
144 procedure :: check_congruent => soca_fields_check_congruent
147 procedure :: check_subset => soca_fields_check_subset
155 procedure :: add => soca_fields_add
158 procedure :: axpy => soca_fields_axpy
161 procedure :: dot_prod => soca_fields_dotprod
164 procedure :: gpnorm => soca_fields_gpnorm
167 procedure :: mul => soca_fields_mul
170 procedure :: sub => soca_fields_sub
173 procedure :: ones => soca_fields_ones
176 procedure :: zeros => soca_fields_zeros
184 procedure :: read => soca_fields_read
187 procedure :: write_file=> soca_fields_write_file
190 procedure :: write_rst => soca_fields_write_rst
198 procedure :: update_halos => soca_fields_update_halos
201 procedure :: colocate => soca_fields_colocate
208 procedure :: serial_size => soca_fields_serial_size
211 procedure :: serialize => soca_fields_serialize
214 procedure :: deserialize => soca_fields_deserialize
237 subroutine soca_field_copy(self, rhs)
241 call self%check_congruent(rhs)
248 end subroutine soca_field_copy
256 subroutine soca_field_update_halo(self, geom)
258 type(
soca_geom),
pointer,
intent(in) :: geom
260 call mpp_update_domains(self%val, geom%Domain%mpp_domain)
261 end subroutine soca_field_update_halo
274 subroutine soca_field_stencil_interp(self, geom, interp2d)
276 type(
soca_geom),
pointer,
intent(in) :: geom
277 type(horiz_interp_type),
intent(in) :: interp2d
280 real(kind=kind_real),
allocatable :: val(:,:,:)
282 allocate(val, mold=self%val)
285 call horiz_interp_spherical(interp2d, &
286 & val(geom%isd:geom%ied, geom%jsd:geom%jed,k), &
287 & self%val(geom%isc:geom%iec, geom%jsc:geom%jec,k))
289 call self%update_halo(geom)
290 end subroutine soca_field_stencil_interp
298 subroutine soca_field_check_congruent(self, rhs)
303 if ( self%nz /= rhs%nz )
call abor1_ftn(
"soca_field: self%nz /= rhs%nz")
304 if ( self%name /= rhs%name )
call abor1_ftn(
"soca_field: self%name /= rhs%name")
305 if (
size(shape(self%val)) /=
size(shape(rhs%val)) ) &
306 call abor1_ftn(
"soca_field: shape of self%val /= rhs%val")
307 do i =1,
size(shape(self%val))
308 if (
size(self%val, dim=i) /=
size(rhs%val, dim=i)) &
309 call abor1_ftn(
"soca_field: shape of self%val /= rhs%val")
311 end subroutine soca_field_check_congruent
318 subroutine soca_field_delete(self)
338 subroutine soca_fields_init_vars(self, vars)
340 character(len=:),
allocatable,
intent(in) :: vars(:)
344 allocate(self%fields(
size(vars)))
346 self%fields(i)%name = trim(vars(i))
349 self%fields(i)%metadata = self%geom%fields_metadata%get(self%fields(i)%name)
351 select case(self%fields(i)%metadata%grid)
353 self%fields(i)%lon => self%geom%lon
354 self%fields(i)%lat => self%geom%lat
355 if (self%fields(i)%metadata%masked) &
356 self%fields(i)%mask => self%geom%mask2d
358 self%fields(i)%lon => self%geom%lonu
359 self%fields(i)%lat => self%geom%latu
360 if (self%fields(i)%metadata%masked) &
361 self%fields(i)%mask => self%geom%mask2du
363 self%fields(i)%lon => self%geom%lonv
364 self%fields(i)%lat => self%geom%latv
365 if (self%fields(i)%metadata%masked) &
366 self%fields(i)%mask => self%geom%mask2dv
368 call abor1_ftn(
'soca_fields::create(): Illegal grid '// &
369 self%fields(i)%metadata%grid // &
370 ' given for ' // self%fields(i)%name)
374 if (self%fields(i)%name == self%fields(i)%metadata%getval_name_surface)
then
378 select case(self%fields(i)%metadata%levels)
384 call abor1_ftn(
'soca_fields::create(): Illegal levels '//self%fields(i)%metadata%levels// &
385 ' given for ' // self%fields(i)%name)
390 self%fields(i)%nz = nz
391 allocate(self%fields(i)%val(&
392 self%geom%isd:self%geom%ied, &
393 self%geom%jsd:self%geom%jed, &
405 subroutine soca_fields_create(self, geom, vars)
407 type(
soca_geom),
pointer,
intent(inout) :: geom
408 type(oops_variables),
intent(inout) :: vars
410 character(len=:),
allocatable :: vars_str(:)
414 if (
associated(self%fields)) &
415 call abor1_ftn(
"soca_fields::create(): object already allocated")
421 allocate(
character(len=1024) :: vars_str(vars%nvars()))
423 vars_str(i) = trim(vars%variable(i))
425 call soca_fields_init_vars(self, vars_str)
429 end subroutine soca_fields_create
436 subroutine soca_fields_delete(self)
442 do i = 1,
size(self%fields)
443 call self%fields(i)%delete()
445 deallocate(self%fields)
459 subroutine soca_fields_copy(self, rhs)
463 character(len=:),
allocatable :: vars_str(:)
468 if (.not.
associated(self%fields))
then
469 self%geom => rhs%geom
470 allocate(
character(len=1024) :: vars_str(size(rhs%fields)))
471 do i=1,
size(vars_str)
472 vars_str(i) = rhs%fields(i)%name
474 call soca_fields_init_vars(self, vars_str)
479 do i=1,
size(self%fields)
480 call rhs%get(self%fields(i)%name, rhs_fld)
481 call self%fields(i)%copy(rhs_fld)
493 subroutine soca_fields_get(self, name, field)
495 character(len=*),
intent(in) :: name
496 type(
soca_field),
pointer,
intent(out) :: field
501 do i=1,
size(self%fields)
502 if (trim(name) == self%fields(i)%name)
then
503 field => self%fields(i)
509 call abor1_ftn(
"soca_fields::get(): cannot find field "//trim(name))
517 function soca_fields_has(self, name)
result(res)
519 character(len=*),
intent(in) :: name
525 do i=1,
size(self%fields)
526 if (trim(name) == self%fields(i)%name)
then
538 subroutine soca_fields_update_halos(self)
542 do i=1,
size(self%fields)
543 call self%fields(i)%update_halo(self%geom)
545 end subroutine soca_fields_update_halos
552 subroutine soca_fields_ones(self)
556 do i = 1,
size(self%fields)
557 self%fields(i)%val = 1.0_kind_real
560 end subroutine soca_fields_ones
567 subroutine soca_fields_zeros(self)
571 do i = 1,
size(self%fields)
572 self%fields(i)%val = 0.0_kind_real
575 end subroutine soca_fields_zeros
585 subroutine soca_fields_add(self, rhs)
591 call self%check_congruent(rhs)
594 do i=1,
size(self%fields)
595 self%fields(i)%val = self%fields(i)%val + rhs%fields(i)%val
597 end subroutine soca_fields_add
607 subroutine soca_fields_sub(self, rhs)
613 call self%check_congruent(rhs)
616 do i=1,
size(self%fields)
617 self%fields(i)%val = self%fields(i)%val - rhs%fields(i)%val
619 end subroutine soca_fields_sub
627 subroutine soca_fields_mul(self, zz)
629 real(kind=kind_real),
intent(in) :: zz
632 do i=1,
size(self%fields)
633 self%fields(i)%val = zz * self%fields(i)%val
635 end subroutine soca_fields_mul
645 subroutine soca_fields_axpy(self, zz, rhs)
647 real(kind=kind_real),
intent(in) :: zz
654 call self%check_subset(rhs)
656 do i=1,
size(self%fields)
657 f_lhs => self%fields(i)
658 if (.not. rhs%has(f_lhs%name)) cycle
659 call rhs%get(f_lhs%name, f_rhs)
660 f_lhs%val = f_lhs%val + zz *f_rhs%val
662 end subroutine soca_fields_axpy
670 subroutine soca_fields_dotprod(self, rhs, zprod)
673 real(kind=kind_real),
intent(out) :: zprod
675 real(kind=kind_real) :: local_zprod
676 integer :: ii, jj, kk, n
680 call self%check_congruent(rhs)
683 local_zprod = 0.0_kind_real
684 do n=1,
size(self%fields)
685 field1 => self%fields(n)
686 field2 => rhs%fields(n)
689 do ii = self%geom%isc, self%geom%iec
690 do jj = self%geom%jsc, self%geom%jec
692 if (
associated(field1%mask))
then
693 if (field1%mask(ii,jj) < 1) cycle
698 local_zprod = local_zprod + field1%val(ii,jj,kk) * field2%val(ii,jj,kk)
705 call self%geom%f_comm%allreduce(local_zprod, zprod, fckit_mpi_sum())
706 end subroutine soca_fields_dotprod
732 subroutine soca_fields_read(self, f_conf, vdate)
734 type(fckit_configuration),
intent(in) :: f_conf
735 type(datetime),
intent(inout) :: vdate
737 integer,
parameter :: max_string_length=800
738 character(len=max_string_length) :: ocn_filename, sfc_filename, ice_filename, wav_filename, filename
739 character(len=:),
allocatable :: basename, incr_filename
742 logical :: vert_remap=.false.
743 character(len=max_string_length) :: remap_filename
744 real(kind=kind_real),
allocatable :: h_common(:,:,:)
745 type(restart_file_type),
target :: ocean_restart, sfc_restart, ice_restart, wav_restart
746 type(restart_file_type) :: ocean_remap_restart
747 type(restart_file_type),
pointer :: restart
749 integer :: isd, ied, jsd, jed
750 integer :: isc, iec, jsc, jec
751 integer :: i, j, nz, n
752 type(remapping_cs) :: remapCS
753 character(len=:),
allocatable :: str
754 real(kind=kind_real),
allocatable :: h_common_ij(:), hocn_ij(:), varocn_ij(:), varocn2_ij(:)
755 logical :: read_sfc, read_ice, read_wav
756 type(
soca_field),
pointer :: field, field2, hocn, mld, layer_depth
758 if ( f_conf%has(
"read_from_file") ) &
759 call f_conf%get_or_die(
"read_from_file", iread)
761 call self%get(
"hocn", hocn)
764 isd = self%geom%isd ; ied = self%geom%ied
765 jsd = self%geom%jsd ; jed = self%geom%jed
769 if ( f_conf%has(
"remap_filename") )
then
771 call f_conf%get_or_die(
"remap_filename", str)
773 allocate(h_common(isd:ied,jsd:jed,nz))
774 h_common = 0.0_kind_real
778 idr = register_restart_field(ocean_remap_restart, remap_filename,
'h', h_common, &
779 domain=self%geom%Domain%mpp_domain)
780 call restore_state(ocean_remap_restart, directory=
'')
781 call free_restart_type(ocean_remap_restart)
788 call f_conf%get_or_die(
"date", str)
789 call datetime_set(str, vdate)
795 if ((iread==1).or.(iread==3))
then
798 call f_conf%get_or_die(
"basename", str)
800 call f_conf%get_or_die(
"ocn_filename", str)
801 ocn_filename = trim(basename) // trim(str)
806 if ( f_conf%has(
"sfc_filename") )
then
807 call f_conf%get_or_die(
"basename", str)
809 call f_conf%get_or_die(
"sfc_filename", str)
810 sfc_filename = trim(basename)//trim(str)
816 if ( f_conf%has(
"ice_filename") )
then
817 call f_conf%get_or_die(
"basename", str)
819 call f_conf%get_or_die(
"ice_filename", str)
820 ice_filename = trim(basename)//trim(str)
826 if ( f_conf%has(
"wav_filename") )
then
827 call f_conf%get_or_die(
"basename", str)
829 call f_conf%get_or_die(
"wav_filename", str)
830 wav_filename = trim(basename)//trim(str)
836 do i=1,
size(self%fields)
837 if(self%fields(i)%metadata%io_name /=
"")
then
839 select case(self%fields(i)%metadata%io_file)
841 filename = ocn_filename
842 restart => ocean_restart
844 if (sfc_filename ==
"") cycle
845 filename = sfc_filename
846 restart => sfc_restart
849 filename = ice_filename
850 restart => ice_restart
853 filename = wav_filename
854 restart => wav_restart
857 call abor1_ftn(
'read_file(): illegal io_file: '//self%fields(i)%metadata%io_file)
861 if (self%fields(i)%nz == 1)
then
862 idr = register_restart_field(restart, filename, self%fields(i)%metadata%io_name, &
863 self%fields(i)%val(:,:,1), domain=self%geom%Domain%mpp_domain)
865 idr = register_restart_field(restart, filename, self%fields(i)%metadata%io_name, &
866 self%fields(i)%val(:,:,:), domain=self%geom%Domain%mpp_domain)
871 call restore_state(ocean_restart, directory=
'')
872 call free_restart_type(ocean_restart)
874 call restore_state(sfc_restart, directory=
'')
875 call free_restart_type(sfc_restart)
878 call restore_state(ice_restart, directory=
'')
879 call free_restart_type(ice_restart)
882 call restore_state(wav_restart, directory=
'')
883 call free_restart_type(wav_restart)
889 isc = self%geom%isc ; iec = self%geom%iec
890 jsc = self%geom%jsc ; jec = self%geom%jec
893 if (self%has(
"layer_depth"))
then
894 call self%get(
"layer_depth", layer_depth)
895 call self%geom%thickness2depth(hocn%val, layer_depth%val)
899 if (self%has(
"mld") .and. self%has(
"layer_depth"))
then
900 call self%get(
"tocn", field)
901 call self%get(
"socn", field2)
902 call self%get(
"mld", mld)
908 &layer_depth%val(i,j,:),&
909 &self%geom%lon(i,j),&
917 allocate(h_common_ij(nz), hocn_ij(nz), varocn_ij(nz), varocn2_ij(nz))
918 call initialize_remapping(remapcs,
'PCM')
921 h_common_ij = h_common(i,j,:)
922 hocn_ij = hocn%val(i,j,:)
924 do n=1,
size(self%fields)
925 field => self%fields(n)
926 select case(field%name)
930 if (
associated(field%mask) .and. field%mask(i,j).eq.1)
then
931 varocn_ij = field%val(i,j,:)
932 call remapping_core_h(remapcs, nz, h_common_ij, varocn_ij,&
933 &nz, hocn_ij, varocn2_ij)
934 field%val(i,j,:) = varocn2_ij
936 field%val(i,j,:) = 0.0_kind_real
943 deallocate(h_common_ij, hocn_ij, varocn_ij, varocn2_ij)
944 call end_remapping(remapcs)
948 do n=1,
size(self%fields)
949 field => self%fields(n)
950 call mpp_update_domains(field%val, self%geom%Domain%mpp_domain)
955 call f_conf%get_or_die(
"date", str)
956 call datetime_set(str, vdate)
962 end subroutine soca_fields_read
973 subroutine soca_fields_gpnorm(self, nf, pstat)
975 integer,
intent(in) :: nf
976 real(kind=kind_real),
intent(out) :: pstat(3, nf)
978 logical :: mask(self%geom%isc:self%geom%iec, self%geom%jsc:self%geom%jec)
979 real(kind=kind_real) :: ocn_count, local_ocn_count, tmp(3)
980 integer :: jj, isc, iec, jsc, jec
984 isc = self%geom%isc ; iec = self%geom%iec
985 jsc = self%geom%jsc ; jec = self%geom%jec
988 do jj=1,
size(self%fields)
989 call self%get(self%fields(jj)%name, field)
992 if (.not.
associated(field%mask))
then
995 mask = field%mask(isc:iec, jsc:jec) > 0.0
997 local_ocn_count = count(mask)
998 call self%geom%f_comm%allreduce(local_ocn_count, ocn_count, fckit_mpi_sum())
1001 call fldinfo(field%val(isc:iec,jsc:jec,:), mask, tmp)
1002 call self%geom%f_comm%allreduce(tmp(1), pstat(1,jj), fckit_mpi_min())
1003 call self%geom%f_comm%allreduce(tmp(2), pstat(2,jj), fckit_mpi_max())
1004 call self%geom%f_comm%allreduce(tmp(3), pstat(3,jj), fckit_mpi_sum())
1005 pstat(3,jj) = pstat(3,jj)/ocn_count
1007 end subroutine soca_fields_gpnorm
1016 subroutine soca_fields_check_congruent(self, rhs)
1023 if (
size(self%fields) /=
size(rhs%fields)) &
1024 call abor1_ftn(
"soca_fields: contains different number of fields")
1027 do i=1,
size(self%fields)
1028 if (self%fields(i)%name /= rhs%fields(i)%name) &
1029 call abor1_ftn(
"soca_fields: field have different names")
1030 do j = 1,
size(shape(self%fields(i)%val))
1031 if (
size(self%fields(i)%val, dim=j) /=
size(rhs%fields(i)%val, dim=j) )
then
1032 call abor1_ftn(
"soca_fields: field '"//self%fields(i)%name//
"' has different dimensions")
1036 end subroutine soca_fields_check_congruent
1044 subroutine soca_fields_check_subset(self, rhs)
1052 do i=1,
size(self%fields)
1053 if (.not. rhs%has(self%fields(i)%name)) &
1054 call abor1_ftn(
"soca_fields: self is not a subset of rhs")
1055 call rhs%get(self%fields(i)%name, fld)
1056 do j = 1,
size(shape(fld%val))
1057 if (
size(self%fields(i)%val, dim=j) /=
size(fld%val, dim=j) )
then
1058 call abor1_ftn(
"soca_fields: field '"//self%fields(i)%name//
"' has different dimensions")
1062 end subroutine soca_fields_check_subset
1071 subroutine soca_fields_write_file(self, filename)
1073 character(len=*),
intent(in) :: filename
1078 call set_domain( self%geom%Domain%mpp_domain )
1081 do ii = 1,
size(self%fields)
1082 call write_data( filename, self%fields(ii)%name, self%fields(ii)%val(:,:,:), self%geom%Domain%mpp_domain)
1086 call write_data( filename,
"rossby_radius", self%geom%rossby_radius, self%geom%Domain%mpp_domain)
1089 end subroutine soca_fields_write_file
1097 subroutine soca_fields_write_rst(self, f_conf, vdate)
1099 type(fckit_configuration),
intent(in) :: f_conf
1100 type(datetime),
intent(inout) :: vdate
1102 integer,
parameter :: max_string_length=800
1103 character(len=max_string_length) :: ocn_filename, sfc_filename, ice_filename, wav_filename, filename
1104 type(restart_file_type),
target :: ocean_restart, sfc_restart, ice_restart, wav_restart
1105 type(restart_file_type),
pointer :: restart
1108 logical :: write_sfc, write_ice, write_wav
1122 do i=1,
size(self%fields)
1123 field => self%fields(i)
1124 if (len_trim(field%metadata%io_file) /= 0)
then
1126 select case(field%metadata%io_file)
1128 filename = ocn_filename
1129 restart => ocean_restart
1131 filename = sfc_filename
1132 restart => sfc_restart
1135 filename = ice_filename
1136 restart => ice_restart
1139 filename = wav_filename
1140 restart => wav_restart
1143 call abor1_ftn(
'soca_write_restart(): illegal io_file: '//field%metadata%io_file)
1147 if (field%nz == 1)
then
1148 idr = register_restart_field( restart, filename, field%metadata%io_name, &
1149 field%val(:,:,1), domain=self%geom%Domain%mpp_domain)
1151 idr = register_restart_field( restart, filename, field%metadata%io_name, &
1152 field%val(:,:,:), domain=self%geom%Domain%mpp_domain)
1158 call save_restart(ocean_restart, directory=
'')
1159 call free_restart_type(ocean_restart)
1161 call save_restart(sfc_restart, directory=
'')
1162 call free_restart_type(sfc_restart)
1165 call save_restart(ice_restart, directory=
'')
1166 call free_restart_type(ice_restart)
1169 call save_restart(wav_restart, directory=
'')
1170 call free_restart_type(wav_restart)
1174 end subroutine soca_fields_write_rst
1181 subroutine soca_fields_colocate(self, cgridlocout)
1183 character(len=1),
intent(in) :: cgridlocout
1186 real(kind=kind_real),
allocatable :: val(:,:,:)
1187 real(kind=kind_real),
pointer :: lon_out(:,:) => null()
1188 real(kind=kind_real),
pointer :: lat_out(:,:) => null()
1190 type(horiz_interp_type) :: interp2d
1193 select case(cgridlocout)
1202 lon_out => self%geom%lon
1203 lat_out => self%geom%lat
1205 call abor1_ftn(
'soca_fields::colocate(): unknown c-grid location '// cgridlocout)
1209 do i=1,
size(self%fields)
1212 if (self%fields(i)%metadata%grid == cgridlocout) cycle
1216 call horiz_interp_spherical_new(interp2d, &
1217 & real(deg2rad*self%fields(i)%lon(g%isd:g%ied,g%jsd:g%jed), 8), &
1218 & real(deg2rad*self%fields(i)%lat(g%isd:g%ied,g%jsd:g%jed), 8), &
1219 & real(deg2rad*lon_out(g%isc:g%iec,g%jsc:g%jec), 8), &
1220 & real(deg2rad*lat_out(g%isc:g%iec,g%jsc:g%jec), 8))
1223 if (
allocated(val))
deallocate(val)
1224 allocate(val, mold=self%fields(i)%val)
1225 val = self%fields(i)%val
1228 do k = 1, self%fields(i)%nz
1229 call self%fields(i)%stencil_interp(self%geom, interp2d)
1233 self%fields(i)%metadata%grid = cgridlocout
1234 select case(cgridlocout)
1243 self%fields(i)%lon => self%geom%lon
1244 self%fields(i)%lat => self%geom%lat
1248 call horiz_interp_spherical_del(interp2d)
1250 end subroutine soca_fields_colocate
1258 subroutine soca_fields_serial_size(self, geom, vec_size)
1261 integer,
intent(out) :: vec_size
1267 do i=1,
size(self%fields)
1268 vec_size = vec_size +
size(self%fields(i)%val)
1271 end subroutine soca_fields_serial_size
1279 subroutine soca_fields_serialize(self, geom, vec_size, vec)
1282 integer,
intent(in) :: vec_size
1283 real(kind=kind_real),
intent(out) :: vec(vec_size)
1285 integer :: index, i, nn
1289 do i=1,
size(self%fields)
1290 nn =
size(self%fields(i)%val)
1291 vec(index:index+nn-1) = reshape(self%fields(i)%val, (/ nn /) )
1295 end subroutine soca_fields_serialize
1302 subroutine soca_fields_deserialize(self, geom, vec_size, vec, index)
1305 integer,
intent(in) :: vec_size
1306 real(kind=kind_real),
intent(in) :: vec(vec_size)
1307 integer,
intent(inout) :: index
1312 do i=1,
size(self%fields)
1313 nn =
size(self%fields(i)%val)
1314 self%fields(i)%val = reshape(vec(index+1:index+1+nn), shape(self%fields(i)%val))
1318 end subroutine soca_fields_deserialize
1332 real(kind=kind_real),
intent(in) :: fld(:,:,:)
1333 logical,
intent(in) :: mask(:,:)
1334 real(kind=kind_real),
intent(out) :: info(3)
1337 real(kind=kind_real) :: tmp(3,
size(fld, dim=3))
1340 do z = 1,
size(tmp, dim=2)
1341 tmp(1,z) = minval(fld(:,:,z), mask=mask)
1342 tmp(2,z) = maxval(fld(:,:,z), mask=mask)
1343 tmp(3,z) = sum( fld(:,:,z), mask=mask) /
size(fld, dim=3)
1347 info(1) = minval(tmp(1,:))
1348 info(2) = maxval(tmp(2,:))
1349 info(3) = sum( tmp(3,:))
1362 type(fckit_configuration),
intent(in) :: f_conf
1363 integer,
intent(in) :: length
1364 type(datetime),
intent(in) :: vdate
1365 character(len=3),
optional,
intent(in) :: domain_type
1368 character(len=length) :: fdbdir, expver, typ, validitydate, referencedate, sstep, &
1370 type(datetime) :: rdate
1371 type(duration) :: step
1373 character(len=:),
allocatable :: str
1375 call f_conf%get_or_die(
"datadir", str)
1377 call f_conf%get_or_die(
"exp", str)
1379 call f_conf%get_or_die(
"type", str)
1382 if (
present(domain_type))
then
1383 expver = trim(domain_type)//
"."//expver
1385 expver =
"ocn.ice."//expver
1387 if (typ==
"ens")
then
1388 call f_conf%get_or_die(
"member", str)
1390 lenfn = len_trim(fdbdir) + 1 + len_trim(expver) + 1 + len_trim(typ) + 1 + len_trim(mmb)
1391 prefix = trim(fdbdir) //
"/" // trim(expver) //
"." // trim(typ) //
"." // trim(mmb)
1393 lenfn = len_trim(fdbdir) + 1 + len_trim(expver) + 1 + len_trim(typ)
1394 prefix = trim(fdbdir) //
"/" // trim(expver) //
"." // trim(typ)
1397 if (typ==
"fc" .or. typ==
"ens")
then
1398 call f_conf%get_or_die(
"date", str)
1400 call datetime_to_string(vdate, validitydate)
1401 call datetime_create(trim(referencedate), rdate)
1402 call datetime_diff(vdate, rdate, step)
1403 call duration_to_string(step, sstep)
1404 lenfn = lenfn + 1 + len_trim(referencedate) + 1 + len_trim(sstep)
1405 soca_genfilename = trim(prefix) //
"." // trim(referencedate) //
"." // trim(sstep)
1408 if (typ==
"an" .or. typ==
"incr")
then
1409 call datetime_to_string(vdate, validitydate)
1410 lenfn = lenfn + 1 + len_trim(validitydate)
1415 &
call abor1_ftn(
"fields:genfilename: filename too long")
1417 if (
allocated(str) )
deallocate(str)
1422 end module soca_fields_mod
Handle fields for the model.
character(len=length) function soca_genfilename(f_conf, length, vdate, domain_type)
Generate filename (based on oops/qg)
subroutine fldinfo(fld, mask, info)
Calculate min/max/mean statistics for a given field, using a mask.
various utility functions
real(kind=kind_real) function, public soca_mld(sp, pt, p, lon, lat)
calculate mixed layer depth from temp/salinity profile
Holds all data and metadata related to a single field variable.
A collection of soca_field types representing a collective state or increment.