Loading [MathJax]/extensions/tex2jax.js
MPAS-JEDI
All Classes Namespaces Files Functions Variables Typedefs Macros Pages
mpas_fields_mod.F90
Go to the documentation of this file.
1 ! (C) Copyright 2017 UCAR
2 !
3 ! This software is licensed under the terms of the Apache Licence Version 2.0
4 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5 
7 
8 use fckit_configuration_module, only: fckit_configuration
9 use fckit_log_module, only: fckit_log
10 use iso_c_binding
11 
12 !oops
13 use datetime_mod
14 use kinds, only: kind_real
15 use oops_variables_mod, only: oops_variables
16 use string_utils, only: swap_name_member
17 use unstructured_interpolation_mod
18 
19 ! saber
20 use interpolatorbump_mod, only: bump_interpolator
21 
22 !ufo
23 use ufo_vars_mod, only: maxvarlen, ufo_vars_getindex
24 use ufo_locations_mod
25 use ufo_geovals_mod, only: ufo_geovals
26 
27 !MPAS-Model
28 use atm_core, only: atm_simulation_clock_init, atm_compute_output_diagnostics
29 use mpas_constants
30 use mpas_derived_types
31 use mpas_kind_types, only: strkind
32 use mpas_pool_routines
33 use mpas_stream_manager
34 use mpas_timekeeping
35 
36 !mpas-jedi
38 use mpas_geom_mod
39 use mpas4da_mod
41 
42 implicit none
43 
44 private
45 
56 
57 ! ------------------------------------------------------------------------------
58 
59  !> Fortran derived type to hold MPAS field
60  type :: mpas_fields
61  private
62 
63  type (mpas_geom), pointer, public :: geom ! grid and MPI infos
64  type (mpas_streammanager_type), pointer, public :: manager
65  type (mpas_clock_type), pointer, public :: clock
66  integer, public :: nf ! Number of variables in subFields
67  character(len=MAXVARLEN), allocatable, public :: fldnames(:) ! Variable identifiers
68  type (mpas_pool_type), pointer, public :: subfields => null() !---> state variables (to be analyzed)
69  integer, public :: nf_ci ! Number of variables in CI
70  character(len=MAXVARLEN), allocatable, public :: fldnames_ci(:) ! Control increment identifiers
71 
72  contains
73 
74  procedure :: axpy => axpy_
75  procedure :: dot_prod => dot_prod_
76  procedure :: gpnorm => gpnorm_
77  procedure :: random => random_
78  procedure :: rms => rms_
79  procedure :: self_add => self_add_
80  procedure :: self_schur => self_schur_
81  procedure :: self_mult => self_mult_
82  procedure :: self_sub => self_sub_
83  procedure :: zeros => zeros_
84  procedure :: ones => ones_
85 
86  procedure :: change_resol => change_resol_fields
87  procedure :: copy => copy_fields
88  procedure :: create => create_fields
89  procedure :: populate => populate_subfields
90  procedure :: delete => delete_fields
91  procedure :: read_file => read_fields
92  procedure :: write_file => write_fields
93  procedure :: serial_size => serial_size
94  procedure :: serialize => serialize_fields
95  procedure :: deserialize => deserialize_fields
96 
97  !has
98  generic, public :: has => has_field, has_fields
99  procedure :: has_field
100  procedure :: has_fields
101 
102  !get
103  generic, public :: get => &
104  get_data, &
109  procedure :: &
110  get_data, &
115 
116  !copy_to
117  generic, public :: copy_to => &
122  procedure :: &
127 
128  !copy_to_ad
129  generic, public :: copy_to_ad => &
134  procedure :: &
139 
140  !copy_from
141  generic, public :: copy_from => &
146  procedure :: &
151 
152  !push_back
153  generic, public :: push_back => &
158  procedure :: &
163 
164  end type mpas_fields
165 
166 ! abstract interface
167 !
168 ! ! ------------------------------------------------------------------------------
169 !
170 ! subroutine read_file_(self, f_conf, vdate)
171 ! import mpas_fields, fckit_configuration, datetime
172 ! implicit none
173 ! class(mpas_fields), intent(inout) :: self
174 ! type(fckit_configuration), intent(in) :: f_conf
175 ! type(datetime), intent(inout) :: vdate
176 ! end subroutine read_file_
177 !
178 ! ! ------------------------------------------------------------------------------
179 !
180 ! end interface
181 
182  character(len=MAXVARLEN) :: mpas_hydrometeor_fields(6) = &
183  [ character(len=maxvarlen) :: &
184  "qc", "qi", "qr", "qs", "qg", "qh" ]
185  character(len=MAXVARLEN) :: mpas_re_fields(3) = &
186  [ character(len=maxvarlen) :: &
187  "re_cloud", "re_ice ", "re_snow " ]
188  character(len=MAXVARLEN), parameter :: cellcenteredwindfields(2) = &
189  [character(len=maxvarlen) :: &
190  'uReconstructZonal', 'uReconstructMeridional']
191  character(len=MAXVARLEN), parameter :: moisturefields(2) = &
192  [character(len=maxvarlen) :: &
193  'qv', 'spechum']
194  character(len=MAXVARLEN), parameter :: analysisthermofields(2) = &
195  [character(len=maxvarlen) :: &
196  'surface_pressure', 'temperature']
197  character(len=MAXVARLEN), parameter :: modelthermofields(4) = &
198  [character(len=maxvarlen) :: &
199  'qv', 'pressure', 'rho', 'theta']
200 
201 
202  integer, parameter :: max_string=8000
203  character(max_string) :: message
204 
205 #define LISTED_TYPE mpas_fields
206 
207 !> Linked list interface - defines registry_t type
208 #include <oops/util/linkedList_i.f>
209 
210 !> Global registry
211 type(registry_t) :: mpas_fields_registry
212 
213 ! ------------------------------------------------------------------------------
214 
215 contains
216 
217 ! ------------------------------------------------------------------------------
218 
219 !> Linked list implementation
220 #include <oops/util/linkedList_c.f>
221 
222 ! ------------------------------------------------------------------------------
223 
224 subroutine create_fields(self, geom, vars, vars_ci)
225 
226  implicit none
227 
228  class(mpas_fields), intent(inout) :: self
229  type(mpas_geom), intent(in), pointer :: geom
230  type(oops_variables), intent(in) :: vars, vars_ci
231 
232  integer :: ivar, ierr
233 
234  self % nf = vars % nvars()
235  allocate(self % fldnames(self % nf))
236  do ivar = 1, self % nf
237  self % fldnames(ivar) = trim(vars % variable(ivar))
238  end do
239 
240  self % nf_ci = vars_ci % nvars()
241  allocate(self % fldnames_ci(self % nf_ci))
242  do ivar = 1, self % nf_ci
243  self % fldnames_ci(ivar) = trim(vars_ci % variable(ivar))
244  end do
245 
246  write(message,*) "DEBUG: create_fields: self % fldnames(:) =",self % fldnames(:)
247  call fckit_log%debug(message)
248 
249  ! link geom
250  if (associated(geom)) then
251  self % geom => geom
252  else
253  call abor1_ftn("--> create_fields: geom not associated")
254  end if
255 
256  ! clock creation
257  allocate(self % clock)
258  call atm_simulation_clock_init(self % clock, self % geom % domain % blocklist % configs, ierr)
259  if ( ierr .ne. 0 ) then
260  call abor1_ftn("--> create_fields: atm_simulation_clock_init problem")
261  end if
262 
263  call self%populate()
264 
265  return
266 
267 end subroutine create_fields
268 
269 ! ------------------------------------------------------------------------------
270 
271 subroutine populate_subfields(self)
272 
273  implicit none
274  class(mpas_fields), intent(inout) :: self
275 
276  call da_template_pool(self % geom, self % subFields, self % nf, self % fldnames)
277 
278 end subroutine populate_subfields
279 
280 ! ------------------------------------------------------------------------------
281 
282 subroutine delete_fields(self)
283 
284  implicit none
285  class(mpas_fields), intent(inout) :: self
286  integer :: ierr = 0
287 
288  if (allocated(self % fldnames)) deallocate(self % fldnames)
289  if (allocated(self % fldnames_ci)) deallocate(self % fldnames_ci)
290 
291  call fckit_log%debug('--> delete_fields: deallocate subFields Pool')
292  call delete_pool(self % subFields)
293 
294  call mpas_destroy_clock(self % clock, ierr)
295  if ( ierr .ne. 0 ) then
296  call fckit_log%info ('--> delete_fields deallocate clock failed')
297  end if
298  call fckit_log%debug('--> delete_fields done')
299 
300  return
301 
302 end subroutine delete_fields
303 
304 ! ------------------------------------------------------------------------------
305 
306 subroutine delete_pool(pool)
307 
308  implicit none
309  type(mpas_pool_type), pointer, intent(inout) :: pool
310 
311  if (associated(pool)) then
312  call mpas_pool_destroy_pool(pool)
313  end if
314 
315 end subroutine delete_pool
316 
317 ! ------------------------------------------------------------------------------
318 
319 subroutine copy_fields(self,rhs)
320 
321  implicit none
322  class(mpas_fields), intent(inout) :: self
323  class(mpas_fields), intent(in) :: rhs
324  type (mpas_time_type) :: rhs_time
325  integer :: ierr
326 
327  call fckit_log%debug('--> copy_fields: copy subFields Pool')
328 
329  self % nf = rhs % nf
330  if (allocated(self % fldnames)) deallocate(self % fldnames)
331  allocate(self % fldnames(self % nf))
332  self % fldnames(:) = rhs % fldnames(:)
333 
334  self % nf_ci = rhs % nf_ci
335  if (allocated(self % fldnames_ci)) deallocate(self % fldnames_ci)
336  allocate(self % fldnames_ci(self % nf_ci))
337  self % fldnames_ci(:) = rhs % fldnames_ci(:)
338 
339  rhs_time = mpas_get_clock_time(rhs % clock, mpas_now, ierr)
340  call mpas_set_clock_time(self % clock, rhs_time, mpas_now)
341 
342  call copy_pool(rhs % subFields, self % subFields)
343 
344  call fckit_log%debug('--> copy_fields done')
345 
346 end subroutine copy_fields
347 
348 ! ------------------------------------------------------------------------------
349 
350 subroutine copy_pool(pool_src, pool)
351 
352  implicit none
353  type(mpas_pool_type), pointer, intent(in) :: pool_src
354  type(mpas_pool_type), pointer, intent(inout) :: pool
355 
356  ! Duplicate the members of pool_src into pool and
357  ! do a deep copy of the fields
358  call delete_pool(pool)
359  call mpas_pool_create_pool(pool)
360  call mpas_pool_clone_pool(pool_src, pool)
361 
362 end subroutine copy_pool
363 
364 ! ------------------------------------------------------------------------------
365 
366 subroutine read_fields(self, f_conf, vdate)
367 
368  implicit none
369  class(mpas_fields), intent(inout) :: self !< Field
370  type(fckit_configuration), intent(in) :: f_conf !< Configuration
371  type(datetime), intent(inout) :: vdate !< DateTime
372  character(len=:), allocatable :: str
373  character(len=20) :: sdate
374  type (MPAS_Time_type) :: local_time
375  character (len=StrKIND) :: dateTimeString, streamID, time_string, filename, temp_filename
376  integer :: ierr = 0, ngrid
377  type (mpas_pool_type), pointer :: state, diag, mesh
378  type (field2DReal), pointer :: pressure, pressure_base, pressure_p
379 
380  call fckit_log%debug('--> read_fields')
381  call f_conf%get_or_die("date",str)
382  sdate = str
383  call datetime_set(sdate, vdate)
384 
385  call f_conf%get_or_die("filename",str)
386  call swap_name_member(f_conf, str)
387  temp_filename = str
388  write(message,*) '--> read_fields: Reading ',trim(temp_filename)
389  call fckit_log%debug(message)
390  !temp_filename = 'restart.$Y-$M-$D_$h.$m.$s.nc'
391  ! GD look at oops/src/util/datetime_mod.F90
392  ! we probably need to extract from vdate a string to enforce the reading ..
393  ! and then can be like this ....
394  ! TODO: we can get streamID from yaml
395  !streamID = 'restart'
396  !streamID = 'input'
397  streamid = 'output'
398  !streamID = 'da'
399  ierr = 0
400  self % manager => self % geom % domain % streamManager
401  datetimestring = '$Y-$M-$D_$h:$m:$s'
402  call cvt_oopsmpas_date(sdate,datetimestring,1)
403  write(message,*) '--> read_fields: dateTimeString: ',trim(datetimestring)
404  call fckit_log%debug(message)
405  call mpas_set_time(local_time, datetimestring=datetimestring, ierr=ierr)
406  call mpas_set_clock_time(self % clock, local_time, mpas_now)
407  call mpas_set_clock_time(self % geom % domain % clock, local_time, mpas_start_time)
408  call mpas_expand_string(datetimestring, -1, temp_filename, filename)
409  call mpas_stream_mgr_set_property(self % manager, streamid, mpas_stream_property_filename, filename)
410  write(message,*) '--> read_fields: Reading ',trim(filename)
411  call fckit_log%debug(message)
412  call mpas_stream_mgr_read(self % manager, streamid=streamid, &
413  & when=datetimestring, rightnow=.true., ierr=ierr)
414  if ( ierr .ne. 0 ) then
415  write(message,*) '--> read_fields: MPAS_stream_mgr_read failed ierr=',ierr
416  call abor1_ftn(message)
417  end if
418 
419  !==TODO: Specific part when reading parameterEst. for BUMP.
420  ! : They write/read a list of variables directly.
421  if (f_conf%has("no_transf")) then
422  call f_conf%get_or_die("no_transf",ierr)
423  if(ierr .eq. 1) then
424  call da_copy_all2sub_fields(self % geom % domain, self % subFields)
425  return
426  endif
427  endif
428 
429  !(1) diagnose pressure
430  call mpas_pool_get_subpool(self % geom % domain % blocklist % structs, 'diag', diag)
431  call mpas_pool_get_field(diag, 'pressure_p', pressure_p)
432  call mpas_pool_get_field(diag, 'pressure_base', pressure_base)
433  call mpas_pool_get_field(diag, 'pressure', pressure)
434  ngrid = self % geom % nCellsSolve
435  pressure%array(:,1:ngrid) = pressure_base%array(:,1:ngrid) + pressure_p%array(:,1:ngrid)
436 
437  !(2) copy all to subFields & diagnose temperature
438  call update_diagnostic_fields(self % geom % domain, self % subFields, self % geom % nCellsSolve)
439 
440 end subroutine read_fields
441 
442 
443 subroutine update_diagnostic_fields(domain, subFields, ngrid)
444 
445  implicit none
446  type (domain_type), pointer, intent(inout) :: domain
447  type (mpas_pool_type), pointer, intent(inout) :: subfields
448  integer, intent(in) :: ngrid
449  type (field2dreal), pointer :: theta, pressure, temperature, specific_humidity
450  type (field3dreal), pointer :: scalars
451  type (mpas_pool_type), pointer :: state
452  integer, pointer :: index_qv
453 
454  !(1) copy all to subFields
455  call da_copy_all2sub_fields(domain, subfields)
456 
457  !(2) diagnose temperature
458  !Special case: Convert theta and pressure to temperature
459  ! Convert water vapor mixing ratio to specific humidity [ q = w / (1 + w) ]
460  !NOTE: This formula is somewhat different with MPAS one's (in physics, they use "exner")
461  ! : If T diagnostic is added in, for example, subroutine atm_compute_output_diagnostics,
462  ! : we need to include "exner" in stream_list.for.reading
463 
464  call mpas_pool_get_field(domain % blocklist % allFields, 'theta', theta)
465  call mpas_pool_get_field(domain % blocklist % allFields, 'pressure', pressure)
466  call mpas_pool_get_field(subfields, 'temperature', temperature)
467  call mpas_pool_get_field(domain % blocklist % allFields, 'scalars', scalars)
468  call mpas_pool_get_field(subfields, 'spechum', specific_humidity)
469 
470  call mpas_pool_get_subpool(domain % blocklist % structs,'state',state)
471  call mpas_pool_get_dimension(state, 'index_qv', index_qv)
472 
473  call theta_to_temp(theta % array(:,1:ngrid), pressure % array(:,1:ngrid), temperature % array(:,1:ngrid))
474  call w_to_q( scalars % array(index_qv,:,1:ngrid) , specific_humidity % array(:,1:ngrid) )
475 
476 end subroutine update_diagnostic_fields
477 
478 ! ------------------------------------------------------------------------------
479 
480 subroutine write_fields(self, f_conf, vdate)
481 
482  implicit none
483  class(mpas_fields), intent(inout) :: self !< Field
484  type(fckit_configuration), intent(in) :: f_conf !< Configuration
485  type(datetime), intent(in) :: vdate !< DateTime
486  character(len=:), allocatable :: str
487  character(len=20) :: validitydate
488  integer :: ierr
489  type (MPAS_Time_type) :: fld_time, write_time
490  character (len=StrKIND) :: dateTimeString, dateTimeString2, streamID, time_string, filename, temp_filename
491 
492  call da_copy_sub2all_fields(self % geom % domain, self % subFields)
493 
494  call datetime_to_string(vdate, validitydate)
495  write(message,*) '--> write_fields: ',trim(validitydate)
496  call fckit_log%debug(message)
497  call f_conf%get_or_die("filename",str)
498  call swap_name_member(f_conf, str)
499  temp_filename = str
500  write(message,*) '--> write_fields: ',trim(temp_filename)
501  call fckit_log%debug(message)
502  !temp_filename = 'restart.$Y-$M-$D_$h.$m.$s.nc'
503  ! GD look at oops/src/util/datetime_mod.F90
504  ! we probably need to extract from vdate a string to enforce the reading ..
505  ! and then can be like this ....
506  datetimestring = '$Y-$M-$D_$h:$m:$s'
507  call cvt_oopsmpas_date(validitydate,datetimestring,-1)
508  ierr = 0
509  call mpas_set_time(write_time, datetimestring=datetimestring, ierr=ierr)
510  fld_time = mpas_get_clock_time(self % clock, mpas_now, ierr)
511  call mpas_get_time(fld_time, datetimestring=datetimestring2, ierr=ierr)
512  write(message,*) 'check time --> write_fields: write_time,fld_time: ',trim(datetimestring),trim(datetimestring2)
513  call fckit_log%debug(message)
514  call mpas_expand_string(datetimestring, -1, trim(temp_filename), filename)
515 
516  self % manager => self % geom % domain % streamManager
517  ! TODO: we can get streamID from yaml
518  ! TODO: should we pick different stream lists for mpas_state and mpas_increment?
519  !streamID = 'restart'
520  streamid = 'output'
521  !streamID = 'da'
522  call mpas_stream_mgr_set_property(self % manager, streamid, mpas_stream_property_filename, filename)
523 
524  write(message,*) '--> write_fields: writing ',trim(filename)
525  call fckit_log%debug(message)
526  call mpas_stream_mgr_write(self % geom % domain % streamManager, streamid=streamid, &
527  forcewritenow=.true., writetime=datetimestring, ierr=ierr)
528  if ( ierr .ne. 0 ) then
529  write(message,*) '--> write_fields: MPAS_stream_mgr_write failed ierr=',ierr
530  call abor1_ftn(message)
531  end if
532 
533 end subroutine write_fields
534 
535 ! ------------------------------------------------------------------------------
536 
537 subroutine change_resol_fields(self,rhs)
538 
539  implicit none
540  class(mpas_fields), intent(inout) :: self
541  class(mpas_fields), intent(in) :: rhs
542 
543  if (self%geom%nCells == rhs%geom%nCells .and. self%geom%nVertLevels == rhs%geom%nVertLevels) then
544  call self%copy(rhs)
545  else if (self%geom%nVertLevels == rhs%geom%nVertLevels) then
546  call interpolate_fields(self,rhs)
547  else
548  write(message,*) '--> change_resol_fields: ',self%geom%nCells, rhs%geom%nCells, self%geom%nVertLevels, rhs%geom%nVertLevels
549  call fckit_log%info(message)
550  call abor1_ftn("mpas_fields_mod:change_resol_fields: VertLevels dimension mismatch")
551  endif
552 
553 end subroutine change_resol_fields
554 
555 ! ------------------------------------------------------------------------------
556 
557 subroutine zeros_(self)
558 
559  implicit none
560  class(mpas_fields), intent(inout) :: self
561 
562  call da_constant(self % subFields, mpas_jedi_zero_kr, fld_select = self % fldnames_ci)
563 
564 end subroutine zeros_
565 
566 ! ------------------------------------------------------------------------------
567 
568 subroutine ones_(self)
569 
570  implicit none
571  class(mpas_fields), intent(inout) :: self
572 
573  call da_constant(self % subFields, mpas_jedi_one_kr, fld_select = self % fldnames_ci)
574 
575 end subroutine ones_
576 
577 ! ------------------------------------------------------------------------------
578 
579 subroutine random_(self)
580 
581  implicit none
582  class(mpas_fields), intent(inout) :: self
583 
584  call da_random(self % subFields, fld_select = self % fldnames_ci)
585 
586 end subroutine random_
587 
588 ! ------------------------------------------------------------------------------
589 
590 subroutine gpnorm_(self, nf, pstat)
591 
592  implicit none
593  class(mpas_fields), intent(in) :: self
594  integer, intent(in) :: nf
595  real(kind=kind_real), intent(out) :: pstat(3, nf)
596 
597  call da_gpnorm(self % subFields, self % geom % domain % dminfo, nf, pstat, fld_select = self % fldnames_ci(1:nf))
598 
599 end subroutine gpnorm_
600 
601 ! ------------------------------------------------------------------------------
602 
603 subroutine rms_(self, prms)
604 
605  implicit none
606  class(mpas_fields), intent(in) :: self
607  real(kind=kind_real), intent(out) :: prms
608 
609  call da_fldrms(self % subFields, self % geom % domain % dminfo, prms, fld_select = self % fldnames_ci)
610 
611 end subroutine rms_
612 
613 ! ------------------------------------------------------------------------------
614 
615 subroutine self_add_(self,rhs)
616 
617  implicit none
618  class(mpas_fields), intent(inout) :: self
619  class(mpas_fields), intent(in) :: rhs
620  character(len=StrKIND) :: kind_op
621 
622  kind_op = 'add'
623  call da_operator(trim(kind_op), self % subFields, rhs % subFields, fld_select = self % fldnames_ci)
624 
625 end subroutine self_add_
626 
627 ! ------------------------------------------------------------------------------
628 
629 subroutine self_schur_(self,rhs)
630 
631  implicit none
632  class(mpas_fields), intent(inout) :: self
633  class(mpas_fields), intent(in) :: rhs
634  character(len=StrKIND) :: kind_op
635 
636  kind_op = 'schur'
637  call da_operator(trim(kind_op), self % subFields, rhs % subFields, fld_select = self % fldnames_ci)
638 
639 end subroutine self_schur_
640 
641 ! ------------------------------------------------------------------------------
642 
643 subroutine self_sub_(self,rhs)
644 
645  implicit none
646  class(mpas_fields), intent(inout) :: self
647  class(mpas_fields), intent(in) :: rhs
648  character(len=StrKIND) :: kind_op
649 
650  kind_op = 'sub'
651  call da_operator(trim(kind_op), self % subFields, rhs % subFields, fld_select = self % fldnames_ci)
652 
653 end subroutine self_sub_
654 
655 ! ------------------------------------------------------------------------------
656 
657 subroutine self_mult_(self,zz)
658 
659  implicit none
660  class(mpas_fields), intent(inout) :: self
661  real(kind=kind_real), intent(in) :: zz
662 
663  call da_self_mult(self % subFields, zz)
664 
665 end subroutine self_mult_
666 
667 ! ------------------------------------------------------------------------------
668 
669 subroutine axpy_(self,zz,rhs)
670 
671  implicit none
672  class(mpas_fields), intent(inout) :: self
673  real(kind=kind_real), intent(in) :: zz
674  class(mpas_fields), intent(in) :: rhs
675 
676  call da_axpy(self % subFields, rhs % subFields, zz, fld_select = self % fldnames_ci)
677 
678 end subroutine axpy_
679 
680 ! ------------------------------------------------------------------------------
681 
682 subroutine dot_prod_(self,fld,zprod)
683 
684  implicit none
685  class(mpas_fields), intent(in) :: self, fld
686  real(kind=kind_real), intent(inout) :: zprod
687 
688  call da_dot_product(self % subFields, fld % subFields, self % geom % domain % dminfo, zprod)
689 
690 end subroutine dot_prod_
691 
692 ! ------------------------------------------------------------------------------
693 
694 !> \brief Populates subfields of self using rhs
695 !!
696 !! \details **interpolate_fields** This subroutine is called when creating
697 !! a new mpas_fields type (self) using an existing mpas_fields (rhs) as a source that
698 !! has a different geometry/mesh (but the same number of VertLevels). It populates
699 !! the subfields of self, interpolating the data from rhs. It can use either
700 !! bump or unstructured interpolation for the interpolation routine.
701 subroutine interpolate_fields(self,rhs)
702 
703  implicit none
704  class(mpas_fields), intent(inout) :: self !< mpas_fields being populated
705  class(mpas_fields), intent(in) :: rhs !< mpas_fields used as source
706 
707  type(bump_interpolator) :: bumpinterp
708  type(unstrc_interp) :: unsinterp
709  type (mpas_pool_iterator_type) :: poolItr
710  real(kind=kind_real), allocatable :: interp_in(:,:), interp_out(:,:)
711  real (kind=kind_real), dimension(:), pointer :: r1d_ptr
712  real (kind=kind_real), dimension(:,:), pointer :: r2d_ptr
713  integer, dimension(:), pointer :: i1d_ptr
714  integer, dimension(:,:), pointer :: i2d_ptr
715  integer :: rhs_nCells, self_nCells, maxlevels, nlevels, jlev
716  logical :: use_bump_interp
717  integer, allocatable :: rhsDims(:)
718 
719  use_bump_interp = rhs%geom%use_bump_interpolation
720 
721  if (use_bump_interp) then
722  call initialize_bumpinterp(self%geom, rhs%geom, bumpinterp)
723  else
724  call initialize_uns_interp(self%geom, rhs%geom, unsinterp)
725  endif
726 
727  ! Interpolate field from rhs mesh to self mesh using pre-calculated weights
728  ! ----------------------------------------------------------------------------------
729  maxlevels = rhs%geom%nVertLevelsP1
730  rhs_ncells = rhs%geom%nCellsSolve
731  self_ncells = self%geom%nCellsSolve
732 
733  allocate(interp_in(rhs_ncells, maxlevels))
734  allocate(interp_out(self_ncells, maxlevels))
735 
736  call mpas_pool_begin_iteration(rhs%subFields)
737  do while ( mpas_pool_get_next_member(rhs%subFields, poolitr) )
738  if (poolitr % memberType == mpas_pool_field) then
739  write(message,*) 'poolItr % nDims , poolItr % memberName =', poolitr % nDims , trim(poolitr % memberName)
740  call fckit_log%debug(message)
741  ! Get the rhs fields out of the rhs%subFields pool and into an array that
742  ! can be passed to the interpolator apply functions.
743  ! (Four cases to cover: 1D/2D and real/integer variable.)
744  if (poolitr % nDims == 1) then
745  nlevels = 1
746  if (poolitr % dataType == mpas_pool_integer) then
747  call mpas_pool_get_array(rhs%subFields, trim(poolitr % memberName), i1d_ptr)
748  interp_in(:,1) = real( i1d_ptr(1:rhs_ncells), kind_real)
749  else if (poolitr % dataType == mpas_pool_real) then
750  call mpas_pool_get_array(rhs%subFields, trim(poolitr % memberName), r1d_ptr)
751  interp_in(:,1) = r1d_ptr(1:rhs_ncells)
752  endif
753  else if (poolitr % nDims == 2) then
754  rhsdims = getsolvedimsizes(rhs%subFields, poolitr%memberName)
755  nlevels = rhsdims(1)
756  if (nlevels > maxlevels) then
757  write(message,*) '--> interpolate_fields: nlevels > maxlevels, ', nlevels, maxlevels
758  call abor1_ftn(message)
759  endif
760  if (poolitr % dataType == mpas_pool_integer) then
761  call mpas_pool_get_array(rhs%subFields, trim(poolitr % memberName), i2d_ptr)
762  interp_in(1:rhs_ncells,1:nlevels) = real( transpose(i2d_ptr(1:nlevels,1:rhs_ncells)), kind_real )
763  else if (poolitr % dataType == mpas_pool_real) then
764  call mpas_pool_get_array(rhs%subFields, trim(poolitr % memberName), r2d_ptr)
765  interp_in(1:rhs_ncells,1:nlevels) = transpose(r2d_ptr(1:nlevels,1:rhs_ncells))
766  endif
767  else
768  write(message,*) '--> interpolate_fields: poolItr % nDims == ',poolitr % nDims,' not handled'
769  call abor1_ftn(message)
770  endif
771 
772  if (use_bump_interp) then
773  call bumpinterp%apply(interp_in(:,1:nlevels), &
774  interp_out(:,1:nlevels), &
775  trans_in=.false.)
776  else
777  do jlev = 1, nlevels
778  call unsinterp%apply(interp_in(:,jlev),interp_out(:,jlev))
779  end do
780  endif
781 
782  ! Put the interpolated results into the self%subFields pool
783  if (poolitr % nDims == 1) then
784  if (poolitr % dataType == mpas_pool_integer) then
785  call mpas_pool_get_array(self%subFields, trim(poolitr % memberName), i1d_ptr)
786  i1d_ptr(1:self_ncells) = int(interp_out(:,1))
787  else if (poolitr % dataType == mpas_pool_real) then
788  call mpas_pool_get_array(self%subFields, trim(poolitr % memberName), r1d_ptr)
789  r1d_ptr(1:self_ncells) = interp_out(:,1)
790  endif
791  else if (poolitr % nDims == 2) then
792  if (poolitr % dataType == mpas_pool_integer) then
793  call mpas_pool_get_array(self%subFields, trim(poolitr % memberName), i2d_ptr)
794  i2d_ptr(1:nlevels,1:self_ncells) = transpose(int(interp_out(1:self_ncells,1:nlevels)))
795  else if (poolitr % dataType == mpas_pool_real) then
796  call mpas_pool_get_array(self%subFields, trim(poolitr % memberName), r2d_ptr)
797  r2d_ptr(1:nlevels,1:self_ncells) = transpose(interp_out(1:self_ncells,1:nlevels))
798  endif
799  endif
800  endif
801  end do !- end of pool iteration
802  deallocate(interp_in)
803  deallocate(interp_out)
804  if (allocated(rhsdims)) deallocate(rhsdims)
805 
806 end subroutine interpolate_fields
807 ! ------------------------------------------------------------------------------
808 
809 ! ------------------------------------------------------------------------------
810 
811 !> \brief Initializes a bump interpolation type
812 !!
813 !! \details **initialize_bumpinterp** This subroutine calls bumpinterp%init,
814 !! which calculates the barycentric weights used to interpolate data between the
815 !! geom_from locations and the geom_to locations.
816 subroutine initialize_bumpinterp(geom_to, geom_from, bumpinterp)
817 
818  implicit none
819  class(mpas_geom), intent(in) :: geom_to !< geometry interpolating to
820  class(mpas_geom), intent(in) :: geom_from !< geometry interpolating from
821  type(bump_interpolator), intent(inout) :: bumpinterp !< bump interpolator
822 
823  real(kind=kind_real), allocatable :: lats_to(:), lons_to(:)
824 
825  allocate( lats_to(geom_to%nCellsSolve) )
826  allocate( lons_to(geom_to%nCellsSolve) )
827  lats_to(:) = geom_to%latCell( 1:geom_to%nCellsSolve ) * mpas_jedi_rad2deg_kr !- to Degrees
828  lons_to(:) = geom_to%lonCell( 1:geom_to%nCellsSolve ) * mpas_jedi_rad2deg_kr !- to Degrees
829 
830  call bumpinterp%init(geom_from%f_comm,afunctionspace_in=geom_from%afunctionspace,lon_out=lons_to,lat_out=lats_to, &
831  & nl=geom_from%nVertLevels)
832 
833  ! Release memory
834  ! --------------
835  deallocate(lats_to)
836  deallocate(lons_to)
837 
838 end subroutine initialize_bumpinterp
839 
840 ! --------------------------------------------------------------------------------------------------
841 
842 !> \brief Initializes an unstructured interpolation type
843 !!
844 !! \details **initialize_uns_interp** This subroutine calls unsinterp%create,
845 !! which calculates the barycentric weights used to interpolate data between the
846 !! geom_from locations and the geom_to locations.
847 subroutine initialize_uns_interp(geom_to, geom_from, unsinterp)
848 
849  implicit none
850  class(mpas_geom), intent(in) :: geom_to !< geometry interpolating to
851  class(mpas_geom), intent(in) :: geom_from !< geometry interpolating from
852  type(unstrc_interp), intent(inout) :: unsinterp !< unstructured interpolator
853 
854  integer :: nn, ngrid_from, ngrid_to
855  character(len=8) :: wtype = 'barycent'
856  real(kind=kind_real), allocatable :: lats_from(:), lons_from(:), lats_to(:), lons_to(:)
857 
858  ! Get the Solution dimensions
859  ! ---------------------------
860  ngrid_from = geom_from%nCellsSolve
861  ngrid_to = geom_to%nCellsSolve
862 
863  !Calculate interpolation weight
864  !------------------------------------------
865  allocate( lats_from(ngrid_from) )
866  allocate( lons_from(ngrid_from) )
867  lats_from(:) = geom_from%latCell( 1:ngrid_from ) * mpas_jedi_rad2deg_kr !- to Degrees
868  lons_from(:) = geom_from%lonCell( 1:ngrid_from ) * mpas_jedi_rad2deg_kr !- to Degrees
869  allocate( lats_to(ngrid_to) )
870  allocate( lons_to(ngrid_to) )
871  lats_to(:) = geom_to%latCell( 1:ngrid_to ) * mpas_jedi_rad2deg_kr !- to Degrees
872  lons_to(:) = geom_to%lonCell( 1:ngrid_to ) * mpas_jedi_rad2deg_kr !- to Degrees
873 
874  ! Initialize unsinterp
875  ! ---------------
876  nn = 3 ! number of nearest neigbors
877  call unsinterp%create(geom_from%f_comm, nn, wtype, &
878  ngrid_from, lats_from, lons_from, &
879  ngrid_to, lats_to, lons_to)
880 
881  ! Release memory
882  ! --------------
883  deallocate(lats_from)
884  deallocate(lons_from)
885  deallocate(lats_to)
886  deallocate(lons_to)
887 
888 end subroutine initialize_uns_interp
889 
890 subroutine serial_size(self, vsize)
891 
892  implicit none
893 
894  ! Passed variables
895  class(mpas_fields),intent(in) :: self
896  integer(c_size_t),intent(out) :: vsize !< Size
897 
898  ! Local variables
899  type (mpas_pool_iterator_type) :: poolItr
900  integer, allocatable :: dimSizes(:)
901 
902  ! Initialize
903  vsize = 0
904 
905  call mpas_pool_begin_iteration(self%subFields)
906  do while ( mpas_pool_get_next_member(self%subFields, poolitr) )
907  if (poolitr % memberType == mpas_pool_field) then
908  dimsizes = getsolvedimsizes(self%subFields, poolitr%memberName)
909  vsize = vsize + product(dimsizes)
910  deallocate(dimsizes)
911  endif
912  enddo
913 
914 end subroutine serial_size
915 
916 ! ------------------------------------------------------------------------------
917 
918 subroutine serialize_fields(self, vsize, vect_inc)
919 
920  implicit none
921 
922  ! Passed variables
923  class(mpas_fields),intent(in) :: self !< Increment
924  integer(c_size_t),intent(in) :: vsize !< Size
925  real(kind_real),intent(out) :: vect_inc(vsize) !< Vector
926 
927  ! Local variables
928  integer :: index, nvert, nhoriz, vv, hh
929  type (mpas_pool_iterator_type) :: poolItr
930  integer, allocatable :: dimSizes(:)
931 
932  real (kind=kind_real), dimension(:), pointer :: r1d_ptr_a
933  real (kind=kind_real), dimension(:,:), pointer :: r2d_ptr_a
934  integer, dimension(:), pointer :: i1d_ptr_a
935  integer, dimension(:,:), pointer :: i2d_ptr_a
936 
937  ! Initialize
938  index = 0
939 
940  call mpas_pool_begin_iteration(self%subFields)
941  do while ( mpas_pool_get_next_member(self%subFields, poolitr) )
942  if (poolitr % memberType == mpas_pool_field) then
943  dimsizes = getsolvedimsizes(self%subFields, poolitr%memberName)
944  if (poolitr % nDims == 1) then
945  nhoriz = dimsizes(1)
946  if (poolitr % dataType == mpas_pool_integer) then
947  call mpas_pool_get_array(self%subFields, trim(poolitr % memberName), i1d_ptr_a)
948  do hh = 1, nhoriz
949  vect_inc(index + 1) = real(i1d_ptr_a(hh), kind=kind_real)
950  index = index + 1
951  enddo
952  else if (poolitr % dataType == mpas_pool_real) then
953  call mpas_pool_get_array(self%subFields, trim(poolitr % memberName), r1d_ptr_a)
954  do hh = 1, nhoriz
955  vect_inc(index + 1) = r1d_ptr_a(hh)
956  index = index + 1
957  enddo
958  endif
959  elseif (poolitr % nDims == 2) then
960  nvert = dimsizes(1)
961  nhoriz = dimsizes(2)
962  if (poolitr % dataType == mpas_pool_integer) then
963  call mpas_pool_get_array(self%subFields, trim(poolitr % memberName), i2d_ptr_a)
964  do vv = 1, nvert
965  do hh = 1, nhoriz
966  vect_inc(index + 1) = real(i2d_ptr_a(vv, hh), kind=kind_real)
967  index = index + 1
968  enddo
969  enddo
970  else if (poolitr % dataType == mpas_pool_real) then
971  call mpas_pool_get_array(self%subFields, trim(poolitr % memberName), r2d_ptr_a)
972  do vv = 1, nvert
973  do hh = 1, nhoriz
974  vect_inc(index + 1) = r2d_ptr_a(vv, hh)
975  index = index + 1
976  enddo
977  enddo
978  endif
979  else
980  write(message,*) '--> serialize_fields: poolItr % nDims == ',poolitr % nDims,' not handled'
981  call abor1_ftn(message)
982  endif
983  deallocate(dimsizes)
984  endif
985  enddo
986 
987 end subroutine serialize_fields
988 
989 ! --------------------------------------------------------------------------------------------------
990 
991 subroutine deserialize_fields(self, vsize, vect_inc, index)
992 
993  implicit none
994 
995  ! Passed variables
996  class(mpas_fields),intent(inout) :: self !< Increment
997  integer(c_size_t),intent(in) :: vsize !< Size
998  real(kind_real),intent(in) :: vect_inc(vsize) !< Vector
999  integer(c_size_t),intent(inout) :: index !< Index
1000 
1001  ! Local variables
1002  integer :: nvert, nhoriz, vv, hh
1003  type (mpas_pool_iterator_type) :: poolItr
1004  integer, allocatable :: dimSizes(:)
1005 
1006  real (kind=kind_real), dimension(:), pointer :: r1d_ptr_a
1007  real (kind=kind_real), dimension(:,:), pointer :: r2d_ptr_a
1008  integer, dimension(:), pointer :: i1d_ptr_a
1009  integer, dimension(:,:), pointer :: i2d_ptr_a
1010 
1011  call mpas_pool_begin_iteration(self%subFields)
1012  do while ( mpas_pool_get_next_member(self%subFields, poolitr) )
1013  if (poolitr % memberType == mpas_pool_field) then
1014  dimsizes = getsolvedimsizes(self%subFields, poolitr%memberName)
1015  if (poolitr % nDims == 1) then
1016  nhoriz = dimsizes(1)
1017  if (poolitr % dataType == mpas_pool_integer) then
1018  call mpas_pool_get_array(self%subFields, trim(poolitr % memberName), i1d_ptr_a)
1019  do hh = 1, nhoriz
1020  i1d_ptr_a(hh) = int( vect_inc(index + 1) )
1021  index = index + 1
1022  enddo
1023  else if (poolitr % dataType == mpas_pool_real) then
1024  call mpas_pool_get_array(self%subFields, trim(poolitr % memberName), r1d_ptr_a)
1025  do hh = 1, nhoriz
1026  r1d_ptr_a(hh) = vect_inc(index + 1)
1027  index = index + 1
1028  enddo
1029  endif
1030  elseif (poolitr % nDims == 2) then
1031  nvert = dimsizes(1)
1032  nhoriz = dimsizes(2)
1033  if (poolitr % dataType == mpas_pool_integer) then
1034  call mpas_pool_get_array(self%subFields, trim(poolitr % memberName), i2d_ptr_a)
1035  do vv = 1, nvert
1036  do hh = 1, nhoriz
1037  i2d_ptr_a(vv, hh) = int( vect_inc(index + 1) )
1038  index = index + 1
1039  enddo
1040  enddo
1041  else if (poolitr % dataType == mpas_pool_real) then
1042  call mpas_pool_get_array(self%subFields, trim(poolitr % memberName), r2d_ptr_a)
1043  do vv = 1, nvert
1044  do hh = 1, nhoriz
1045  r2d_ptr_a(vv, hh) = vect_inc(index + 1)
1046  index = index + 1
1047  enddo
1048  enddo
1049  endif
1050  else
1051  write(message,*) '--> deserialize_fields: poolItr % nDims == ',poolitr % nDims,' not handled'
1052  call abor1_ftn(message)
1053  endif
1054  deallocate(dimsizes)
1055  endif
1056  enddo
1057 
1058 end subroutine deserialize_fields
1059 
1060 ! has
1061 function has_field(self, fieldname) result(has)
1062  class(mpas_fields), intent(in) :: self
1063  character(len=*), intent(in) :: fieldname
1064  logical :: has
1065  has = (ufo_vars_getindex(self % fldnames, fieldname) > 0)
1066 end function has_field
1067 
1068 function has_fields(self, fieldnames) result(has)
1069  class(mpas_fields), intent(in) :: self
1070  character(len=*), intent(in) :: fieldnames(:)
1071  integer :: i
1072  logical, allocatable :: has(:)
1073  allocate(has(size(fieldnames)))
1074  do i = 1, size(fieldnames)
1075  has(i) = self%has(fieldnames(i))
1076  end do
1077 end function has_fields
1078 
1079 ! get
1080 subroutine get_data(self, key, data)
1081  class(mpas_fields), intent(in) :: self
1082  character (len=*), intent(in) :: key
1083  type(mpas_pool_data_type), pointer, intent(out) :: data
1084  if (self%has(key)) then
1085  data => pool_get_member(self % subFields, key, mpas_pool_field)
1086  else
1087  write(message,*) 'self%get_data: field not present, ', key
1088  call abor1_ftn(message)
1089  end if
1090 end subroutine get_data
1091 
1092 subroutine get_field_i1(self, key, i1)
1093  class(mpas_fields), intent(in) :: self
1094  character (len=*), intent(in) :: key
1095  type(field1dinteger), pointer, intent(out) :: i1
1096  type(mpas_pool_data_type), pointer :: data
1097  call self%get(key, data)
1098  i1 => data%i1
1099 end subroutine get_field_i1
1100 
1101 subroutine get_field_i2(self, key, i2)
1102  class(mpas_fields), intent(in) :: self
1103  character (len=*), intent(in) :: key
1104  type(field2dinteger), pointer, intent(out) :: i2
1105  type(mpas_pool_data_type), pointer :: data
1106  call self%get(key, data)
1107  i2 => data%i2
1108 end subroutine get_field_i2
1109 
1110 subroutine get_field_r1(self, key, r1)
1111  class(mpas_fields), intent(in) :: self
1112  character (len=*), intent(in) :: key
1113  type(field1dreal), pointer, intent(out) :: r1
1114  type(mpas_pool_data_type), pointer :: data
1115  call self%get(key, data)
1116  r1 => data%r1
1117 end subroutine get_field_r1
1118 
1119 subroutine get_field_r2(self, key, r2)
1120  class(mpas_fields), intent(in) :: self
1121  character (len=*), intent(in) :: key
1122  type(field2dreal), pointer, intent(out) :: r2
1123  type(mpas_pool_data_type), pointer :: data
1124  call self%get(key, data)
1125  r2 => data%r2
1126 end subroutine get_field_r2
1127 
1128 subroutine get_array_i1(self, key, i1)
1129  class(mpas_fields), intent(in) :: self
1130  character (len=*), intent(in) :: key
1131  integer, pointer, intent(out) :: i1(:)
1132  type(mpas_pool_data_type), pointer :: data
1133  call self%get(key, data)
1134  i1 => data%i1%array
1135 end subroutine get_array_i1
1136 
1137 subroutine get_array_i2(self, key, i2)
1138  class(mpas_fields), intent(in) :: self
1139  character (len=*), intent(in) :: key
1140  integer, pointer, intent(out) :: i2(:,:)
1141  type(mpas_pool_data_type), pointer :: data
1142  call self%get(key, data)
1143  i2 => data%i2%array
1144 end subroutine get_array_i2
1145 
1146 subroutine get_array_r1(self, key, r1)
1147  class(mpas_fields), intent(in) :: self
1148  character (len=*), intent(in) :: key
1149  real(kind=kind_real), pointer, intent(out) :: r1(:)
1150  type(mpas_pool_data_type), pointer :: data
1151  call self%get(key, data)
1152  r1 => data%r1%array
1153 end subroutine get_array_r1
1154 
1155 subroutine get_array_r2(self, key, r2)
1156  class(mpas_fields), intent(in) :: self
1157  character (len=*), intent(in) :: key
1158  real(kind=kind_real), pointer, intent(out) :: r2(:,:)
1159  type(mpas_pool_data_type), pointer :: data
1160  call self%get(key, data)
1161  r2 => data%r2%array
1162 end subroutine get_array_r2
1163 
1164 
1165 ! all copy_to and copy_from methods eventually call
1166 ! copy_field_between_pools
1167 subroutine copy_field_between_pools(from, fromKey, to, toKey)
1168  type(mpas_pool_type), pointer, intent(in) :: from
1169  type(mpas_pool_type), pointer, intent(inout) :: to
1170  character (len=*), intent(in) :: fromKey, toKey
1171  type(mpas_pool_data_type), pointer :: toData, fromData
1172  todata => pool_get_member(to, tokey, mpas_pool_field)
1173  if (associated(todata)) then
1174  fromdata => pool_get_member(from, fromkey, mpas_pool_field)
1175  if (associated(fromdata)) then
1176  if (associated(fromdata%r1) .and. associated(todata%r1)) then
1177  todata%r1%array = fromdata%r1%array
1178  else if (associated(fromdata%r2) .and. associated(todata%r2)) then
1179  todata%r2%array = fromdata%r2%array
1180  else if (associated(fromdata%r3) .and. associated(todata%r3)) then
1181  todata%r3%array = fromdata%r3%array
1182  else if (associated(fromdata%i1) .and. associated(todata%i1)) then
1183  todata%i1%array = fromdata%i1%array
1184  else if (associated(fromdata%i2) .and. associated(todata%i2)) then
1185  todata%i2%array = fromdata%i2%array
1186  else
1187  call abor1_ftn('copy_field_between_pools: data mismatch between to/from pools')
1188  end if
1189  else
1190  write(message,*) 'copy_field_between_pools: field not present in "from" pool, ', fromkey
1191  call abor1_ftn(message)
1192  end if
1193  else
1194  write(message,*) 'copy_field_between_pools: field not present in "to" pool, ', tokey
1195  call abor1_ftn(message)
1196  end if
1197 end subroutine copy_field_between_pools
1198 
1199 ! copy_from
1200 subroutine copy_from_other_pool_field(self, selfKey, otherPool, otherKey)
1201  class(mpas_fields), intent(inout) :: self
1202  type(mpas_pool_type), pointer, intent(in) :: otherPool
1203  character (len=*), intent(in) :: selfKey, otherKey
1204  type(mpas_pool_data_type), pointer :: selfData, otherData
1205  call copy_field_between_pools(otherpool, otherkey, self%subFields, selfkey)
1206 end subroutine copy_from_other_pool_field
1207 
1208 subroutine copy_from_other_pool(self, key, otherPool)
1209  class(mpas_fields), intent(inout) :: self
1210  character (len=*), intent(in) :: key
1211  type(mpas_pool_type), pointer, intent(in) :: otherPool
1212  call self%copy_from(key, otherpool, key)
1213 end subroutine copy_from_other_pool
1214 
1215 subroutine copy_from_other_fields_field(self, selfKey, other, otherKey)
1216  class(mpas_fields), intent(inout) :: self
1217  class(mpas_fields), intent(in) :: other
1218  character (len=*), intent(in) :: selfKey, otherKey
1219  call self%copy_from(selfkey, other%subFields, otherkey)
1220 end subroutine copy_from_other_fields_field
1221 
1222 subroutine copy_from_other_fields(self, key, other)
1223  class(mpas_fields), intent(inout) :: self
1224  character (len=*), intent(in) :: key
1225  class(mpas_fields), intent(in) :: other
1226  call self%copy_from(key, other%subFields, key)
1227 end subroutine copy_from_other_fields
1228 
1229 ! copy_to
1230 subroutine copy_to_other_pool_field(self, selfKey, otherPool, otherKey)
1231  class(mpas_fields), intent(in) :: self
1232  type(mpas_pool_type), pointer, intent(inout) :: otherPool
1233  character (len=*), intent(in) :: selfKey, otherKey
1234  type(mpas_pool_data_type), pointer :: selfData, otherData
1235  call copy_field_between_pools(self%subFields, selfkey, otherpool, otherkey)
1236 end subroutine copy_to_other_pool_field
1237 
1238 subroutine copy_to_other_pool(self, key, otherPool)
1239  class(mpas_fields), intent(in) :: self
1240  character (len=*), intent(in) :: key
1241  type(mpas_pool_type), pointer, intent(inout) :: otherPool
1242  call self%copy_to(key, otherpool, key)
1243 end subroutine copy_to_other_pool
1244 
1245 subroutine copy_to_other_fields_field(self, selfKey, other, otherKey)
1246  class(mpas_fields), intent(in) :: self
1247  class(mpas_fields), intent(inout) :: other
1248  character (len=*), intent(in) :: selfKey, otherKey
1249  call self%copy_to(selfkey, other%subFields, otherkey)
1250 end subroutine copy_to_other_fields_field
1251 
1252 subroutine copy_to_other_fields(self, key, other)
1253  class(mpas_fields), intent(in) :: self
1254  character (len=*), intent(in) :: key
1255  class(mpas_fields), intent(inout) :: other
1256  call self%copy_to(key, other%subFields, key)
1257 end subroutine copy_to_other_fields
1258 
1259 ! all copy_to_ad methods eventually call
1260 ! copy_field_between_pools_ad
1261 subroutine copy_field_between_pools_ad(to, toKey, from, fromKey)
1262  type(mpas_pool_type), pointer, intent(inout) :: to
1263  type(mpas_pool_type), pointer, intent(in) :: from
1264  character (len=*), intent(in) :: fromKey, toKey
1265  type(mpas_pool_data_type), pointer :: toData, fromData
1266  todata => pool_get_member(to, tokey, mpas_pool_field)
1267  if (associated(todata)) then
1268  fromdata => pool_get_member(from, fromkey, mpas_pool_field)
1269  if (associated(fromdata)) then
1270  if (associated(fromdata%r1) .and. associated(todata%r1)) then
1271  todata%r1%array = todata%r1%array + fromdata%r1%array
1272  else if (associated(fromdata%r2) .and. associated(todata%r2)) then
1273  todata%r2%array = todata%r2%array + fromdata%r2%array
1274  else if (associated(fromdata%r3) .and. associated(todata%r3)) then
1275  todata%r3%array = todata%r3%array + fromdata%r3%array
1276  else
1277  call abor1_ftn('copy_field_between_pools_ad: data mismatch between to/from pools')
1278  end if
1279  else
1280  write(message,*) 'copy_field_between_pools_ad: field not present in "from" pool, ', fromkey
1281  call abor1_ftn(message)
1282  end if
1283  else
1284  write(message,*) 'copy_field_between_pools_ad: field not present in "to" pool, ', tokey
1285  call abor1_ftn(message)
1286  end if
1287 end subroutine copy_field_between_pools_ad
1288 
1289 ! copy_to_ad
1290 subroutine copy_to_other_pool_field_ad(self, selfKey, otherPool, otherKey)
1291  class(mpas_fields), intent(inout) :: self
1292  type(mpas_pool_type), pointer, intent(in) :: otherPool
1293  character (len=*), intent(in) :: selfKey, otherKey
1294  type(mpas_pool_data_type), pointer :: selfData, otherData
1295  call copy_field_between_pools_ad(self%subFields, selfkey, otherpool, otherkey)
1296 end subroutine copy_to_other_pool_field_ad
1297 
1298 subroutine copy_to_other_pool_ad(self, key, otherPool)
1299  class(mpas_fields), intent(inout) :: self
1300  character (len=*), intent(in) :: key
1301  type(mpas_pool_type), pointer, intent(in) :: otherPool
1302  call self%copy_to_ad(key, otherpool, key)
1303 end subroutine copy_to_other_pool_ad
1304 
1305 subroutine copy_to_other_fields_field_ad(self, selfKey, other, otherKey)
1306  class(mpas_fields), intent(inout) :: self
1307  class(mpas_fields), intent(in) :: other
1308  character (len=*), intent(in) :: selfKey, otherKey
1309  call self%copy_to_ad(selfkey, other%subFields, otherkey)
1310 end subroutine copy_to_other_fields_field_ad
1311 
1312 subroutine copy_to_other_fields_ad(self, key, other)
1313  class(mpas_fields), intent(inout) :: self
1314  character (len=*), intent(in) :: key
1315  class(mpas_fields), intent(in) :: other
1316  call self%copy_to_ad(key, other%subFields, key)
1317 end subroutine copy_to_other_fields_ad
1318 
1319 ! push_back
1320 ! all push_back methods eventually call
1321 ! pool_push_back_field_from_pool
1322 subroutine pool_push_back_field_from_pool(to, toKey, from, fromKey)
1323  type(mpas_pool_type), pointer, intent(inout) :: to
1324  type(mpas_pool_type), pointer, intent(in) :: from
1325  character (len=*), intent(in) :: fromKey, toKey
1326  type(mpas_pool_data_type), pointer :: fromData
1327  type(field1dreal), pointer :: fieldr1
1328  type(field2dreal), pointer :: fieldr2
1329  type(field3dreal), pointer :: fieldr3
1330  type(field1dinteger), pointer :: fieldi1
1331  type(field2dinteger), pointer :: fieldi2
1332  fromdata => pool_get_member(from, fromkey, mpas_pool_field)
1333  if (associated(fromdata)) then
1334  if (associated(fromdata%r1)) then
1335  call mpas_duplicate_field(fromdata%r1, fieldr1)
1336  fieldr1 % fieldName = tokey
1337  call mpas_pool_add_field(to, tokey, fieldr1)
1338  else if (associated(fromdata%r2)) then
1339  call mpas_duplicate_field(fromdata%r2, fieldr2)
1340  fieldr2 % fieldName = tokey
1341  call mpas_pool_add_field(to, tokey, fieldr2)
1342  else if (associated(fromdata%r3)) then
1343  call mpas_duplicate_field(fromdata%r3, fieldr3)
1344  fieldr3 % fieldName = tokey
1345  call mpas_pool_add_field(to, tokey, fieldr3)
1346  else if (associated(fromdata%i1)) then
1347  call mpas_duplicate_field(fromdata%i1, fieldi1)
1348  fieldi1 % fieldName = tokey
1349  call mpas_pool_add_field(to, tokey, fieldi1)
1350  else if (associated(fromdata%i2)) then
1351  call mpas_duplicate_field(fromdata%i2, fieldi2)
1352  fieldi2 % fieldName = tokey
1353  call mpas_pool_add_field(to, tokey, fieldi2)
1354  else
1355  call abor1_ftn('pool_push_back_field_from_pool: data type not supported')
1356  end if
1357  else
1358  write(message,*) 'pool_push_back_field_from_pool: field not present in "from" pool, ', fromkey
1359  call abor1_ftn(message)
1360  end if
1361 end subroutine pool_push_back_field_from_pool
1362 
1363 subroutine push_back_other_pool_field(self, selfKey, otherPool, otherKey)
1364  class(mpas_fields), intent(inout) :: self
1365  type(mpas_pool_type), pointer, intent(in) :: otherPool
1366  character (len=*), intent(in) :: selfKey, otherKey
1367  type(mpas_pool_data_type), pointer :: selfData, otherData
1368  character(len=MAXVARLEN), allocatable :: fldnames(:)
1369  if (self%has(selfkey)) then
1370  write(message,*) 'push_back_other_pool_field: field already present in self, cannot push_back, ', selfkey
1371  call abor1_ftn(message)
1372  end if
1373 
1374  ! Add field to self%subFields pool
1375  call pool_push_back_field_from_pool(self%subFields, selfkey, otherpool, otherkey)
1376 
1377  ! Extend self%fldnames
1378  allocate(fldnames(self%nf+1))
1379  fldnames(1:self%nf) = self%fldnames(:)
1380  fldnames(self%nf+1) = trim(selfkey)
1381  self%nf = self%nf+1
1382  deallocate(self%fldnames)
1383  allocate(self%fldnames(self%nf))
1384  self%fldnames = fldnames
1385  deallocate(fldnames)
1386 end subroutine push_back_other_pool_field
1387 
1388 subroutine push_back_other_pool(self, key, otherPool)
1389  class(mpas_fields), intent(inout) :: self
1390  character (len=*), intent(in) :: key
1391  type(mpas_pool_type), pointer, intent(in) :: otherPool
1392  call self%push_back(key, otherpool, key)
1393 end subroutine push_back_other_pool
1394 
1395 subroutine push_back_other_fields_field(self, selfKey, other, otherKey)
1396  class(mpas_fields), intent(inout) :: self
1397  class(mpas_fields), intent(in) :: other
1398  character (len=*), intent(in) :: selfKey, otherKey
1399  call self%push_back(selfkey, other%subFields, otherkey)
1400 end subroutine push_back_other_fields_field
1401 
1402 subroutine push_back_other_fields(self, key, other)
1403  class(mpas_fields), intent(inout) :: self
1404  character (len=*), intent(in) :: key
1405  class(mpas_fields), intent(in) :: other
1406  call self%push_back(key, other%subFields, key)
1407 end subroutine push_back_other_fields
1408 
1409 end module mpas_fields_mod
elemental subroutine, public w_to_q(mixing_ratio, specific_humidity)
elemental subroutine, public theta_to_temp(theta, pressure, temperature)
subroutine, public da_self_mult(pool_a, zz)
Performs A = A * zz for pool A, zz a real number.
subroutine, public da_dot_product(pool_a, pool_b, dminfo, zprod)
Performs the dot_product given two pools of fields.
subroutine, public da_constant(pool_a, realvalue, fld_select)
Performs A = constant. for pool A.
subroutine, public da_operator(kind_op, pool_a, pool_b, pool_c, fld_select)
Performs A = A 'kind_op' B for pools A and B.
character(len=1024) message
Definition: mpas4da_mod.F90:67
subroutine, public cvt_oopsmpas_date(inString2, outString2, iconv)
subroutine, public da_template_pool(geom, templatePool, nf, fieldnames)
Subset a pool from fields described in geom.
subroutine, public da_fldrms(pool_a, dminfo, fldrms, fld_select)
Performs basic statistics min/max/norm given a pool.
subroutine, public da_copy_all2sub_fields(domain, pool_a)
Performs a copy of allfield to a sub pool A.
subroutine, public da_copy_sub2all_fields(domain, pool_a)
Performs a copy of a sub pool A to allfields.
subroutine, public da_axpy(pool_a, pool_b, zz, fld_select)
Performs A = A + B * zz for pools A and B.
subroutine, public da_gpnorm(pool_a, dminfo, nf, pstat, fld_select)
Performs basic statistics min/max/norm given a pool.
subroutine, public da_random(pool_a, fld_select)
Performs random for pool A.
real(kind=kind_real), parameter mpas_jedi_zero_kr
real(kind=kind_real), parameter mpas_jedi_rad2deg_kr
real(kind=kind_real), parameter mpas_jedi_one_kr
subroutine pool_push_back_field_from_pool(to, toKey, from, fromKey)
subroutine initialize_bumpinterp(geom_to, geom_from, bumpinterp)
Initializes a bump interpolation type.
subroutine serialize_fields(self, vsize, vect_inc)
subroutine random_(self)
subroutine interpolate_fields(self, rhs)
Populates subfields of self using rhs.
subroutine copy_to_other_fields_field_ad(self, selfKey, other, otherKey)
character(len=maxvarlen), dimension(2), parameter, public cellcenteredwindfields
subroutine get_field_r1(self, key, r1)
type(registry_t), public mpas_fields_registry
Linked list interface - defines registry_t type.
subroutine, public create_fields(self, geom, vars, vars_ci)
Linked list implementation.
subroutine push_back_other_fields(self, key, other)
subroutine push_back_other_fields_field(self, selfKey, other, otherKey)
subroutine copy_from_other_pool(self, key, otherPool)
subroutine get_field_r2(self, key, r2)
subroutine axpy_(self, zz, rhs)
subroutine copy_to_other_pool(self, key, otherPool)
subroutine get_field_i2(self, key, i2)
subroutine self_schur_(self, rhs)
subroutine self_add_(self, rhs)
character(len=maxvarlen), dimension(4), parameter, public modelthermofields
subroutine write_fields(self, f_conf, vdate)
subroutine self_mult_(self, zz)
subroutine, public delete_fields(self)
subroutine rms_(self, prms)
character(len=maxvarlen), dimension(3), public mpas_re_fields
logical function, dimension(:), allocatable has_fields(self, fieldnames)
subroutine deserialize_fields(self, vsize, vect_inc, index)
subroutine copy_to_other_pool_field_ad(self, selfKey, otherPool, otherKey)
subroutine get_field_i1(self, key, i1)
integer, parameter max_string
subroutine get_array_r2(self, key, r2)
character(len=maxvarlen), dimension(6), public mpas_hydrometeor_fields
subroutine copy_from_other_fields_field(self, selfKey, other, otherKey)
subroutine get_array_i1(self, key, i1)
subroutine copy_from_other_pool_field(self, selfKey, otherPool, otherKey)
subroutine copy_to_other_fields(self, key, other)
subroutine, public copy_fields(self, rhs)
subroutine read_fields(self, f_conf, vdate)
subroutine zeros_(self)
subroutine get_array_r1(self, key, r1)
subroutine gpnorm_(self, nf, pstat)
subroutine ones_(self)
subroutine, public update_diagnostic_fields(domain, subFields, ngrid)
logical function has_field(self, fieldname)
subroutine get_data(self, key, data)
subroutine serial_size(self, vsize)
subroutine self_sub_(self, rhs)
character(len=maxvarlen), dimension(2), parameter, public moisturefields
subroutine initialize_uns_interp(geom_to, geom_from, unsinterp)
Initializes an unstructured interpolation type.
character(len=maxvarlen), dimension(2), parameter, public analysisthermofields
subroutine copy_from_other_fields(self, key, other)
subroutine copy_to_other_fields_field(self, selfKey, other, otherKey)
subroutine push_back_other_pool_field(self, selfKey, otherPool, otherKey)
subroutine copy_field_between_pools(from, fromKey, to, toKey)
subroutine copy_field_between_pools_ad(to, toKey, from, fromKey)
subroutine get_array_i2(self, key, i2)
subroutine, public copy_pool(pool_src, pool)
subroutine dot_prod_(self, fld, zprod)
subroutine delete_pool(pool)
subroutine copy_to_other_fields_ad(self, key, other)
subroutine copy_to_other_pool_field(self, selfKey, otherPool, otherKey)
subroutine populate_subfields(self)
subroutine copy_to_other_pool_ad(self, key, otherPool)
subroutine push_back_other_pool(self, key, otherPool)
subroutine change_resol_fields(self, rhs)
integer function, dimension(:), allocatable, public getsolvedimsizes(pool, key, dimPool)
Returns an array with the dimension sizes of a pool field member.
Fortran derived type to hold MPAS field.
Fortran derived type to hold geometry definition.