subroutine dyn_mpas_define_scalar_field(self)
! Module(s) from MPAS.
use dyn_mpas_procedures, only: stringify
use mpas_derived_types, only: field3dreal, mpas_pool_type
use mpas_pool_routines, only: mpas_pool_add_dimension, mpas_pool_add_field, mpas_pool_get_field
class(mpas_dynamical_core_type), intent(in) :: self
character(*), parameter :: subname = 'dyn_mpas_subdriver::dyn_mpas_define_scalar_field'
character(strkind) :: cerr
integer :: i, j
integer :: ierr
integer :: time_level
integer, pointer :: index_qv, index_qc, index_tke, index_water_start, index_water_end
type(field3dreal), pointer :: field_3d_real, field_3d_real_alias(:)
type(mpas_pool_type), pointer :: mpas_pool
call self % debug_print(log_level_debug, subname // ' entered')
nullify(index_qv, index_qc, index_tke, index_water_start, index_water_end)
nullify(field_3d_real, field_3d_real_alias)
nullify(mpas_pool)
call self % get_variable_pointer(index_qv, 'dim', 'index_qv')
call self % get_variable_pointer(index_qc, 'dim', 'index_qc')
call self % get_variable_pointer(index_tke, 'dim', 'index_tke')
call self % get_variable_pointer(index_water_start, 'dim', 'moist_start')
call self % get_variable_pointer(index_water_end, 'dim', 'moist_end')
! Define "scalars" field for MPAS.
call self % debug_print(log_level_info, 'Defining MPAS scalars')
call self % get_pool_pointer(mpas_pool, 'state')
! Add scalar dimensions to MPAS "state" pool.
call mpas_pool_add_dimension(mpas_pool, 'index_qv', index_qv)
call mpas_pool_add_dimension(mpas_pool, 'index_qc', index_qc)
call mpas_pool_add_dimension(mpas_pool, 'index_tke', index_tke)
call mpas_pool_add_dimension(mpas_pool, 'moist_start', index_water_start)
call mpas_pool_add_dimension(mpas_pool, 'moist_end', index_water_end)
! MPAS "state" pool has two time levels.
time_level = 2
allocate(field_3d_real_alias(time_level), errmsg=cerr, stat=ierr)
if (ierr /= 0) then
call self % model_error('Failed to allocate field_3d_real_alias' // new_line('') // &
'Allocation returned with ' // stringify([ierr]) // ': ' // trim(adjustl(cerr)), &
subname, __LINE__)
end if
do i = 1, time_level
call mpas_pool_get_field(mpas_pool, 'scalars', field_3d_real, timelevel=i)
if (.not. associated(field_3d_real)) then
call self % model_error('Failed to find variable "scalars"', subname, __LINE__)
end if
do j = 1, self % number_of_constituents
field_3d_real % constituentnames(j) = &
trim(adjustl(self % constituent_name(self % index_mpas_scalar_to_constituent(j))))
! Print information about MPAS scalars. Only do it once.
if (i == 1) then
call self % debug_print(log_level_verbose, 'MPAS scalar index ' // stringify([j]))
call self % debug_print(log_level_verbose, ' MPAS scalar name: ' // &
trim(field_3d_real % constituentnames(j)))
if (self % input_alias(self % index_mpas_scalar_to_constituent(j)) /= '') then
call self % debug_print(log_level_verbose, ' Input alias: ' // &
trim(self % input_alias(self % index_mpas_scalar_to_constituent(j))))
end if
call self % debug_print(log_level_verbose, ' Is water species: ' // &
stringify([self % is_water_species(self % index_mpas_scalar_to_constituent(j))]))
call self % debug_print(log_level_verbose, ' Index mapping from MPAS scalar to constituent: ' // &
stringify([j]) // ' -> ' // stringify([self % index_mpas_scalar_to_constituent(j)]))
end if
end do
if (index_tke > 0) then
field_3d_real % constituentnames(index_tke) = 'tke_for_les'
end if
! Typically in MPAS, each constituent has a single authoritative name. However in CAM-SIMA, constituents may have
! aliases for reading input. Construct an extra "scalars_alias" field in MPAS at run-time to support this feature.
! Remember that an intrinsic assignment on a derived type works like a "shallow copy"; i.e., pointer components
! on the LHS are simply pointer-assigned to the RHS. This is the desired behavior here because we want any
! operations on the "scalars_alias" field to be reflected in the "scalars" field, including the underlying data.
field_3d_real_alias(i) = field_3d_real
field_3d_real_alias(i) % fieldname = 'scalars_alias'
allocate(field_3d_real_alias(i) % constituentnames(size(field_3d_real % constituentnames)), errmsg=cerr, stat=ierr)
if (ierr /= 0) then
call self % model_error('Failed to allocate field_3d_real_alias % constituentnames' // new_line('') // &
'Allocation returned with ' // stringify([ierr]) // ': ' // trim(adjustl(cerr)), &
subname, __LINE__)
end if
field_3d_real_alias(i) % constituentnames(:) = ''
field_3d_real_alias(i) % constituentnames(1:size(self % input_alias)) = &
adjustl(self % input_alias(self % index_mpas_scalar_to_constituent))
nullify(field_3d_real)
end do
! Inform MPAS about the newly constructed field.
call self % get_pool_pointer(mpas_pool, 'all')
call mpas_pool_add_field(mpas_pool, 'scalars_alias', field_3d_real_alias)
nullify(field_3d_real_alias)
nullify(mpas_pool)
! Define "scalars_tend" field for MPAS.
call self % debug_print(log_level_info, 'Defining MPAS scalar tendencies')
call self % get_pool_pointer(mpas_pool, 'tend')
! Add scalar dimensions to MPAS "tend" pool.
call mpas_pool_add_dimension(mpas_pool, 'index_qv', index_qv)
call mpas_pool_add_dimension(mpas_pool, 'index_qc', index_qc)
call mpas_pool_add_dimension(mpas_pool, 'index_tke', index_tke)
call mpas_pool_add_dimension(mpas_pool, 'moist_start', index_water_start)
call mpas_pool_add_dimension(mpas_pool, 'moist_end', index_water_end)
! MPAS "tend" pool only has one time level.
time_level = 1
do i = 1, time_level
call mpas_pool_get_field(mpas_pool, 'scalars_tend', field_3d_real, timelevel=i)
if (.not. associated(field_3d_real)) then
call self % model_error('Failed to find variable "scalars_tend"', subname, __LINE__)
end if
do j = 1, self % number_of_constituents
field_3d_real % constituentnames(j) = &
'tendency_of_' // trim(adjustl(self % constituent_name(self % index_mpas_scalar_to_constituent(j))))
! Print information about MPAS scalar tendencies. Only do it once.
if (i == 1) then
call self % debug_print(log_level_verbose, 'MPAS scalar tendency index ' // stringify([j]))
call self % debug_print(log_level_verbose, ' MPAS scalar tendency name: ' // &
trim(field_3d_real % constituentnames(j)))
call self % debug_print(log_level_verbose, ' Is water species: ' // &
stringify([self % is_water_species(self % index_mpas_scalar_to_constituent(j))]))
call self % debug_print(log_level_verbose, ' Index mapping from MPAS scalar tendency to constituent: ' // &
stringify([j]) // ' -> ' // stringify([self % index_mpas_scalar_to_constituent(j)]))
end if
end do
if (index_tke > 0) then
field_3d_real % constituentnames(index_tke) = 'tendency_of_tke_for_les'
end if
nullify(field_3d_real)
end do
nullify(mpas_pool)
call self % debug_print(log_level_debug, subname // ' completed')
end subroutine dyn_mpas_define_scalar_field