File DryDepCommon_Mod.F90¶
File List > drydep > DryDepCommon_Mod.F90
Go to the documentation of this file
module drydepcommon_mod
use precision_mod, only: fp
! use precision_mod, only: fp
use error_mod, only: cc_success, cc_failure, cc_error, cc_warning, errormanagertype, &
error_invalid_config, error_invalid_state, error_not_found
use configmanager_mod, only: configmanagertype ! ConfigManager integration
use statemanager_mod, only: statemanagertype ! Add StateManager integration
implicit none
private
! Export types
public :: drydepprocessconfig ! New unified process config
public :: drydepconfig
public :: drydepschemeweselyconfig
public :: drydepschemegocartconfig
public :: drydepschemezhangconfig
! Export utility functions
public :: int_to_string
type :: drydepconfig
! Process settings
character(len=32) :: gas_scheme = 'wesely' ! Scheme for gas species
character(len=32) :: aero_scheme = 'gocart' ! Scheme for aerosol species
logical :: is_active = .true.
logical :: diagnostics = .false. ! Diagnostic switch
! Diagnostic species configuration
integer :: n_diagnostic_species = 0
character(len=32), allocatable :: diagnostic_species(:) ! User-defined species for diagnostics
integer, allocatable :: diagnostic_species_id(:) ! Indices mapping diagnostic_species to species_names
real(fp) :: dt_min = 1.0_fp ! Minimum time step (seconds)
real(fp) :: dt_max = 3600.0_fp ! Maximum time step (seconds)
! Species configuration
integer :: n_species = 0
character(len=32), allocatable :: species_names(:)
integer, allocatable :: species_indices(:) ! Indices of drydep species in ChemState
logical, allocatable :: is_gas(:) ! Is gas species (true for gas, false for aerosol)
! Species properties
real(fp), allocatable :: species_dd_DvzAerSnow(:) ! dd_DvzAerSnow for each species
real(fp), allocatable :: species_dd_DvzMinVal_land(:) ! dd_DvzMinVal_land for each species
real(fp), allocatable :: species_dd_DvzMinVal_snow(:) ! dd_DvzMinVal_snow for each species
real(fp), allocatable :: species_dd_f0(:) ! dd_f0 for each species
real(fp), allocatable :: species_dd_hstar(:) ! dd_hstar for each species
real(fp), allocatable :: species_density(:) ! density for each species
logical, allocatable :: species_is_dust(:) ! is_dust for each species
logical, allocatable :: species_is_seasalt(:) ! is_seasalt for each species
real(fp), allocatable :: species_lower_radius(:) ! lower_radius for each species
real(fp), allocatable :: species_mw_g(:) ! mw_g for each species
real(fp), allocatable :: species_radius(:) ! radius for each species
real(fp), allocatable :: species_upper_radius(:) ! upper_radius for each species
! Diagnostic configuration
logical :: output_diagnostics = .true.
real(fp) :: diagnostic_frequency = 3600.0_fp ! Output frequency (seconds)
contains
procedure, public :: validate => validate_drydep_config
procedure, public :: finalize => finalize_drydep_config
procedure, public :: print_summary => print_drydep_config_summary
end type drydepconfig
type :: drydepschemeweselyconfig
! Scheme metadata
character(len=64) :: scheme_name = 'wesely'
character(len=256) :: description = 'Wesely 1989 gas dry deposition scheme'
character(len=64) :: author = 'Wei Li'
character(len=16) :: algorithm_type = 'explicit'
! Process configuration
logical :: affects_full_column = .false. ! Surface-only processing
! Scheme parameters
real(fp) :: scale_factor = 1.0 ! DryDep velocity scale factor
logical :: co2_effect = .true. ! Apply CO2 effect on stomatal conductance
real(fp) :: co2_level = 600.0 ! Ambient CO2 level for stomatal conductance adjustment
real(fp) :: co2_reference = 380.0 ! Reference CO2 level for stomatal conductance adjustment
! Required meteorological fields
integer :: n_required_met_fields = 21
character(len=32) :: required_met_fields(21)
contains
procedure, public :: validate => validate_wesely_config
procedure, public :: finalize => finalize_wesely_config
end type drydepschemeweselyconfig
! wesely scheme uses local variables only - no persistent state type needed
type :: drydepschemegocartconfig
! Scheme metadata
character(len=64) :: scheme_name = 'gocart'
character(len=256) :: description = 'GOCART-2G aerosol dry deposition scheme'
character(len=64) :: author = 'Wei Li & Lacey Holland'
character(len=16) :: algorithm_type = 'explicit'
! Process configuration
logical :: affects_full_column = .false. ! Surface-only processing
! Scheme parameters
real(fp) :: scale_factor = 1.0 ! Dry deposition velocity scale factor
logical :: resuspension = .false. ! Apply resuspension for dry deposition
! Required meteorological fields
integer :: n_required_met_fields = 13
character(len=32) :: required_met_fields(13)
contains
procedure, public :: validate => validate_gocart_config
procedure, public :: finalize => finalize_gocart_config
end type drydepschemegocartconfig
! gocart scheme uses local variables only - no persistent state type needed
type :: drydepschemezhangconfig
! Scheme metadata
character(len=64) :: scheme_name = 'zhang'
character(len=256) :: description = 'Zhang et al. [2001] scheme with Emerson et al. [2020] updates'
character(len=64) :: author = 'Wei Li'
character(len=16) :: algorithm_type = 'explicit'
! Process configuration
logical :: affects_full_column = .false. ! Surface-only processing
! Scheme parameters
real(fp) :: scale_factor = 1.0 ! Dry deposition velocity scale factor
! Required meteorological fields
integer :: n_required_met_fields = 15
character(len=32) :: required_met_fields(15)
contains
procedure, public :: validate => validate_zhang_config
procedure, public :: finalize => finalize_zhang_config
end type drydepschemezhangconfig
! zhang scheme uses local variables only - no persistent state type needed
type :: drydepprocessconfig
! Process metadata
character(len=64) :: process_name = 'drydep'
character(len=16) :: process_version = '1.0.0'
logical :: is_active = .true.
! Process-specific configuration (delegate to DryDepConfig)
type(DryDepConfig) :: drydep_config
! Scheme configurations
! Separate gas and aerosol scheme configurations
type(DryDepSchemeWESELYConfig) :: wesely_config
type(DryDepSchemeGOCARTConfig) :: gocart_config
type(DryDepSchemeZHANGConfig) :: zhang_config
contains
procedure, public :: load_from_config => drydep_process_load_config
procedure, public :: load_species_from_chem_state => load_species_from_chem_state
procedure, public :: validate => drydep_process_validate
procedure, public :: finalize => drydep_process_finalize
procedure, public :: get_active_scheme_config => get_active_scheme_config
procedure, public :: load_wesely_config
procedure, public :: load_gocart_config
procedure, public :: load_zhang_config
procedure, public :: map_diagnostic_species_indices
end type drydepprocessconfig
contains
subroutine validate_drydep_config(this, error_handler)
class(DryDepConfig), intent(inout) :: this
type(ErrorManagerType), intent(inout) :: error_handler
character(len=256) :: error_msg
integer :: rc
! Validate time step bounds
if (this%dt_min <= 0.0_fp) then
call error_handler%report_error(error_invalid_config, &
"Minimum time step must be positive", rc)
return
end if
if (this%dt_max < this%dt_min) then
call error_handler%report_error(error_invalid_config, &
"Maximum time step must be >= minimum time step", rc)
return
end if
! Validate active scheme(s)
! Validate gas scheme
if (trim(this%gas_scheme) /= 'wesely' .and. &
.true.) then
write(error_msg, '(A)') "Invalid gas scheme: " // trim(this%gas_scheme)
call error_handler%report_error(error_invalid_config, error_msg, rc)
return
end if
! Validate aerosol scheme
if (trim(this%aero_scheme) /= 'gocart' .and. &
trim(this%aero_scheme) /= 'zhang' .and. &
.true.) then
write(error_msg, '(A)') "Invalid aerosol scheme: " // trim(this%aero_scheme)
call error_handler%report_error(error_invalid_config, error_msg, rc)
return
end if
end subroutine validate_drydep_config
subroutine print_drydep_config_summary(this)
class(DryDepConfig), intent(in) :: this
write(*, '(A)') "=== DryDep Process Configuration ==="
write(*, '(A,A)') " Gas scheme: ", trim(this%gas_scheme)
write(*, '(A,A)') " Aerosol scheme: ", trim(this%aero_scheme)
write(*, '(A,I0)') " Number of species: ", this%n_species
write(*, '(A,F0.1,A)') " Minimum time step: ", this%dt_min, " s"
write(*, '(A,F0.1,A)') " Maximum time step: ", this%dt_max, " s"
write(*, '(A,L1)') " Output diagnostics: ", this%output_diagnostics
write(*, '(A)') "============================================="
end subroutine print_drydep_config_summary
subroutine finalize_drydep_config(this)
class(DryDepConfig), intent(inout) :: this
! Deallocate species names array
if (allocated(this%species_names)) then
deallocate(this%species_names)
end if
! Deallocate species indices array
if (allocated(this%species_indices)) then
deallocate(this%species_indices)
end if
! Deallocate species properties arrays
if (allocated(this%species_dd_DvzAerSnow)) then
deallocate(this%species_dd_DvzAerSnow)
end if
if (allocated(this%species_dd_DvzMinVal_land)) then
deallocate(this%species_dd_DvzMinVal_land)
end if
if (allocated(this%species_dd_DvzMinVal_snow)) then
deallocate(this%species_dd_DvzMinVal_snow)
end if
if (allocated(this%species_dd_f0)) then
deallocate(this%species_dd_f0)
end if
if (allocated(this%species_dd_hstar)) then
deallocate(this%species_dd_hstar)
end if
if (allocated(this%species_density)) then
deallocate(this%species_density)
end if
if (allocated(this%species_is_dust)) then
deallocate(this%species_is_dust)
end if
if (allocated(this%species_is_seasalt)) then
deallocate(this%species_is_seasalt)
end if
if (allocated(this%species_lower_radius)) then
deallocate(this%species_lower_radius)
end if
if (allocated(this%species_mw_g)) then
deallocate(this%species_mw_g)
end if
if (allocated(this%species_radius)) then
deallocate(this%species_radius)
end if
if (allocated(this%species_upper_radius)) then
deallocate(this%species_upper_radius)
end if
! Deallocate gas/aerosol classification array
if (allocated(this%is_gas)) then
deallocate(this%is_gas)
end if
! Deallocate diagnostic species array
if (allocated(this%diagnostic_species)) then
deallocate(this%diagnostic_species)
end if
! Deallocate diagnostic species indices array
if (allocated(this%diagnostic_species_id)) then
deallocate(this%diagnostic_species_id)
end if
end subroutine finalize_drydep_config
subroutine validate_wesely_config(this, error_handler)
class(DryDepSchemeWESELYConfig), intent(inout) :: this
type(ErrorManagerType), intent(inout) :: error_handler
! TODO: Add scheme-specific validation
end subroutine validate_wesely_config
subroutine finalize_wesely_config(this)
class(DryDepSchemeWESELYConfig), intent(inout) :: this
! Nothing to deallocate for basic configuration
end subroutine finalize_wesely_config
subroutine validate_gocart_config(this, error_handler)
class(DryDepSchemeGOCARTConfig), intent(inout) :: this
type(ErrorManagerType), intent(inout) :: error_handler
! TODO: Add scheme-specific validation
end subroutine validate_gocart_config
subroutine finalize_gocart_config(this)
class(DryDepSchemeGOCARTConfig), intent(inout) :: this
! Nothing to deallocate for basic configuration
end subroutine finalize_gocart_config
subroutine validate_zhang_config(this, error_handler)
class(DryDepSchemeZHANGConfig), intent(inout) :: this
type(ErrorManagerType), intent(inout) :: error_handler
! TODO: Add scheme-specific validation
end subroutine validate_zhang_config
subroutine finalize_zhang_config(this)
class(DryDepSchemeZHANGConfig), intent(inout) :: this
! Nothing to deallocate for basic configuration
end subroutine finalize_zhang_config
function int_to_string(int_val) result(str_val)
integer, intent(in) :: int_val
character(len=32) :: str_val
write(str_val, '(I0)') int_val
str_val = adjustl(str_val)
end function int_to_string
subroutine drydep_process_load_config(this, config_manager, error_handler)
class(DryDepProcessConfig), intent(inout) :: this
type(ConfigManagerType), intent(inout) :: config_manager
type(ErrorManagerType), intent(inout) :: error_handler
character(len=256) :: scheme_name
integer :: rc
! Process reads directly from master YAML structure: processes.drydep
! ConfigManager provides generic YAML access, process handles its own configuration
! Load process metadata
call config_manager%get_string("processes/drydep/name", this%process_name, rc, "drydep")
if (rc /= cc_success) this%process_name = "drydep" ! default
call config_manager%get_string("processes/drydep/version", this%process_version, rc, "1.0.0")
if (rc /= cc_success) this%process_version = "1.0.0" ! default
call config_manager%get_logical("processes/drydep/activate", this%is_active, rc, .true.)
if (rc /= cc_success) this%is_active = .true. ! default
! Load process-specific configuration directly from master YAML
call config_manager%get_string("processes/drydep/gas_scheme", this%drydep_config%gas_scheme, rc, "wesely")
if (rc /= cc_success) then
call error_handler%report_error(error_invalid_config, &
"Missing required 'gas_scheme' in processes/drydep configuration", rc)
return
end if
call config_manager%get_string("processes/drydep/aero_scheme", this%drydep_config%aero_scheme, rc, "")
if (rc /= cc_success) then
call error_handler%report_error(error_invalid_config, &
"Missing required 'aero_scheme' in processes/drydep configuration", rc)
return
end if
! Load diagnostic switch
call config_manager%get_logical("processes/drydep/diagnostics", this%drydep_config%diagnostics, rc, .false.)
if (rc /= cc_success) this%drydep_config%diagnostics = .false. ! Default
! Load diagnostic species list
call config_manager%get_array("processes/drydep/diag_species", this%drydep_config%diagnostic_species, &
rc, default_values=["All"])
if (rc /= cc_success) then
! Default to all species if not specified
allocate(this%drydep_config%diagnostic_species(1))
this%drydep_config%diagnostic_species(1) = "All"
this%drydep_config%n_diagnostic_species = 1
else
! Set the count based on the returned array size
if (allocated(this%drydep_config%diagnostic_species)) then
this%drydep_config%n_diagnostic_species = size(this%drydep_config%diagnostic_species)
else
this%drydep_config%n_diagnostic_species = 0
end if
end if
! Species configuration is loaded from ChemState in load_species_from_chem_state
! The species come from the master species YAML file (CATChem_species.yml)
! and are filtered by is_drydep property
! Load scheme-specific configuration from master YAML
! Load gas scheme configuration
scheme_name = trim(this%drydep_config%gas_scheme)
select case (scheme_name)
case ('wesely')
call this%load_wesely_config(config_manager, error_handler)
case default
call error_handler%report_error(error_invalid_state, &
"Unknown drydep gas scheme: " // trim(scheme_name), rc)
return
end select
! Load aerosol scheme configuration
scheme_name = trim(this%drydep_config%aero_scheme)
select case (scheme_name)
case ('gocart')
call this%load_gocart_config(config_manager, error_handler)
case ('zhang')
call this%load_zhang_config(config_manager, error_handler)
case default
call error_handler%report_error(error_invalid_state, &
"Unknown drydep aerosol scheme: " // trim(scheme_name), rc)
return
end select
end subroutine drydep_process_load_config
subroutine load_species_from_chem_state(this, chem_state, error_handler)
use chemstate_mod, only: chemstatetype
class(DryDepProcessConfig), intent(inout) :: this
type(ChemStateType), pointer, intent(in) :: chem_state
type(ErrorManagerType), intent(inout) :: error_handler
integer :: i, rc
integer :: species_idx
if (.not. associated(chem_state)) then
call error_handler%report_error(error_invalid_state, &
"ChemState not associated in load_species_from_chem_state", rc)
return
end if
! by_metadata mode: Load species by type from ChemState using dynamic metadata flag mapping
! Dynamic mapping: is_drydep -> nSpeciesDryDep and DryDepIndex
this%drydep_config%n_species = chem_state%nSpeciesDryDep
if (this%drydep_config%n_species <= 0) then
call error_handler%report_error(error_invalid_state, &
"No drydep species found in ChemState", rc)
return
end if
! Check if DryDepIndex is allocated and has correct size
if (.not. allocated(chem_state%DryDepIndex)) then
call error_handler%report_error(error_invalid_state, &
"DryDepIndex not allocated in ChemState", rc)
return
end if
if (size(chem_state%DryDepIndex) < this%drydep_config%n_species) then
call error_handler%report_error(error_invalid_state, &
"DryDepIndex size inconsistent with nSpeciesDryDep", rc)
return
end if
! Deallocate existing arrays if allocated
if (allocated(this%drydep_config%species_names)) then
deallocate(this%drydep_config%species_names)
end if
if (allocated(this%drydep_config%species_indices)) then
deallocate(this%drydep_config%species_indices)
end if
! Allocate arrays
allocate(this%drydep_config%species_names(this%drydep_config%n_species))
allocate(this%drydep_config%species_indices(this%drydep_config%n_species))
allocate(this%drydep_config%is_gas(this%drydep_config%n_species))
! Allocate species properties arrays
allocate(this%drydep_config%species_dd_DvzAerSnow(this%drydep_config%n_species))
allocate(this%drydep_config%species_dd_DvzMinVal_land(this%drydep_config%n_species))
allocate(this%drydep_config%species_dd_DvzMinVal_snow(this%drydep_config%n_species))
allocate(this%drydep_config%species_dd_f0(this%drydep_config%n_species))
allocate(this%drydep_config%species_dd_hstar(this%drydep_config%n_species))
allocate(this%drydep_config%species_density(this%drydep_config%n_species))
allocate(this%drydep_config%species_is_dust(this%drydep_config%n_species))
allocate(this%drydep_config%species_is_seasalt(this%drydep_config%n_species))
allocate(this%drydep_config%species_lower_radius(this%drydep_config%n_species))
allocate(this%drydep_config%species_mw_g(this%drydep_config%n_species))
allocate(this%drydep_config%species_radius(this%drydep_config%n_species))
allocate(this%drydep_config%species_upper_radius(this%drydep_config%n_species))
! by_metadata mode: Copy indices from metadata-specific index array using dynamic mapping
! Dynamic mapping: is_drydep -> DryDepIndex
this%drydep_config%species_indices(1:this%drydep_config%n_species) = &
chem_state%DryDepIndex(1:this%drydep_config%n_species)
! Get species names using the indices
do i = 1, this%drydep_config%n_species
if (this%drydep_config%species_indices(i) > 0 .and. &
this%drydep_config%species_indices(i) <= size(chem_state%SpeciesNames)) then
this%drydep_config%species_names(i) = &
trim(chem_state%SpeciesNames(this%drydep_config%species_indices(i)))
else
call error_handler%report_error(error_invalid_state, &
"Invalid species index in species index array", rc)
return
end if
end do
! Load species properties from ChemState
do i = 1, this%drydep_config%n_species
species_idx = this%drydep_config%species_indices(i)
this%drydep_config%species_dd_DvzAerSnow(i) = chem_state%ChemSpecies(species_idx)%dd_DvzAerSnow
this%drydep_config%species_dd_DvzMinVal_land(i) = chem_state%ChemSpecies(species_idx)%dd_DvzMinVal_land
this%drydep_config%species_dd_DvzMinVal_snow(i) = chem_state%ChemSpecies(species_idx)%dd_DvzMinVal_snow
this%drydep_config%species_dd_f0(i) = chem_state%ChemSpecies(species_idx)%dd_f0
this%drydep_config%species_dd_hstar(i) = chem_state%ChemSpecies(species_idx)%dd_hstar
this%drydep_config%species_density(i) = chem_state%ChemSpecies(species_idx)%density
this%drydep_config%species_is_dust(i) = chem_state%ChemSpecies(species_idx)%is_dust
this%drydep_config%species_is_seasalt(i) = chem_state%ChemSpecies(species_idx)%is_seasalt
this%drydep_config%species_lower_radius(i) = chem_state%ChemSpecies(species_idx)%lower_radius
this%drydep_config%species_mw_g(i) = chem_state%ChemSpecies(species_idx)%mw_g
this%drydep_config%species_radius(i) = chem_state%ChemSpecies(species_idx)%radius
this%drydep_config%species_upper_radius(i) = chem_state%ChemSpecies(species_idx)%upper_radius
this%drydep_config%is_gas(i) = chem_state%ChemSpecies(species_idx)%is_gas
end do
end subroutine load_species_from_chem_state
subroutine load_wesely_config(this, config_manager, error_handler)
class(DryDepProcessConfig), intent(inout) :: this
type(ConfigManagerType), intent(inout) :: config_manager
type(ErrorManagerType), intent(inout) :: error_handler
integer :: rc
! Load scheme parameters directly from processes/drydep/wesely/ in master YAML
call config_manager%get_real("processes/drydep/wesely/scale_factor", &
this%wesely_config%scale_factor, rc, 1.0_fp)
if (rc /= cc_success) this%wesely_config%scale_factor = 1.0_fp
call config_manager%get_logical("processes/drydep/wesely/co2_effect", &
this%wesely_config%co2_effect, rc, .true.)
if (rc /= cc_success) this%wesely_config%co2_effect = .true.
call config_manager%get_real("processes/drydep/wesely/co2_level", &
this%wesely_config%co2_level, rc, 600.0_fp)
if (rc /= cc_success) this%wesely_config%co2_level = 600.0_fp
call config_manager%get_real("processes/drydep/wesely/co2_reference", &
this%wesely_config%co2_reference, rc, 380.0_fp)
if (rc /= cc_success) this%wesely_config%co2_reference = 380.0_fp
end subroutine load_wesely_config
subroutine load_gocart_config(this, config_manager, error_handler)
class(DryDepProcessConfig), intent(inout) :: this
type(ConfigManagerType), intent(inout) :: config_manager
type(ErrorManagerType), intent(inout) :: error_handler
integer :: rc
! Load scheme parameters directly from processes/drydep/gocart/ in master YAML
call config_manager%get_real("processes/drydep/gocart/scale_factor", &
this%gocart_config%scale_factor, rc, 1.0_fp)
if (rc /= cc_success) this%gocart_config%scale_factor = 1.0_fp
call config_manager%get_logical("processes/drydep/gocart/resuspension", &
this%gocart_config%resuspension, rc, .false.)
if (rc /= cc_success) this%gocart_config%resuspension = .false.
end subroutine load_gocart_config
subroutine load_zhang_config(this, config_manager, error_handler)
class(DryDepProcessConfig), intent(inout) :: this
type(ConfigManagerType), intent(inout) :: config_manager
type(ErrorManagerType), intent(inout) :: error_handler
integer :: rc
! Load scheme parameters directly from processes/drydep/zhang/ in master YAML
call config_manager%get_real("processes/drydep/zhang/scale_factor", &
this%zhang_config%scale_factor, rc, 1.0_fp)
if (rc /= cc_success) this%zhang_config%scale_factor = 1.0_fp
end subroutine load_zhang_config
subroutine drydep_process_validate(this, state_manager, error_handler)
class(DryDepProcessConfig), intent(inout) :: this
type(StateManagerType), intent(in) :: state_manager
type(ErrorManagerType), intent(inout) :: error_handler
! Validate main config
call this%drydep_config%validate(error_handler)
! Validate scheme-specific config
! Validate gas scheme config
select case (trim(this%drydep_config%gas_scheme))
case ('wesely')
call this%wesely_config%validate(error_handler)
end select
! Validate aerosol scheme config
select case (trim(this%drydep_config%aero_scheme))
case ('gocart')
call this%gocart_config%validate(error_handler)
case ('zhang')
call this%zhang_config%validate(error_handler)
end select
end subroutine drydep_process_validate
subroutine drydep_process_finalize(this)
class(DryDepProcessConfig), intent(inout) :: this
call this%drydep_config%finalize()
call this%wesely_config%finalize()
call this%gocart_config%finalize()
call this%zhang_config%finalize()
end subroutine drydep_process_finalize
function get_active_scheme_config(this, gas_scheme) result(scheme_config)
class(DryDepProcessConfig), intent(in) :: this
logical, optional, intent(in) :: gas_scheme ! If true, return gas scheme; if false, return aerosol scheme
class(*), allocatable :: scheme_config
! For gas/aero differentiated processes, return requested scheme type
if (present(gas_scheme) .and. gas_scheme) then
! Return gas scheme
select case (trim(this%drydep_config%gas_scheme))
case ('wesely')
allocate(scheme_config, source=this%wesely_config)
case default
! Return null
end select
else
! Return aerosol scheme (default or when gas_scheme = false)
select case (trim(this%drydep_config%aero_scheme))
case ('gocart')
allocate(scheme_config, source=this%gocart_config)
case ('zhang')
allocate(scheme_config, source=this%zhang_config)
case default
! Return null
end select
end if
end function get_active_scheme_config
subroutine map_diagnostic_species_indices(this, error_handler)
class(DryDepProcessConfig), intent(inout) :: this
type(ErrorManagerType), intent(inout) :: error_handler
integer :: i, j, rc
character(len=256) :: error_msg
logical :: found_species
! Only proceed if diagnostic species are defined
if (this%drydep_config%n_diagnostic_species == 0) return
! Handle "All" case - map all available species
if (this%drydep_config%n_diagnostic_species == 1 .and. &
trim(this%drydep_config%diagnostic_species(1)) == "All") then
! Deallocate and reallocate for all species
if (allocated(this%drydep_config%diagnostic_species_id)) deallocate(this%drydep_config%diagnostic_species_id)
allocate(this%drydep_config%diagnostic_species_id(this%drydep_config%n_species))
if (allocated(this%drydep_config%diagnostic_species)) deallocate(this%drydep_config%diagnostic_species)
allocate(this%drydep_config%diagnostic_species(this%drydep_config%n_species))
this%drydep_config%n_diagnostic_species = this%drydep_config%n_species
this%drydep_config%diagnostic_species = this%drydep_config%species_names
! Map all species indices (1:n_species)
do i = 1, this%drydep_config%n_species
this%drydep_config%diagnostic_species_id(i) = i
end do
return
end if
! Allocate diagnostic species indices array
if (allocated(this%drydep_config%diagnostic_species_id)) deallocate(this%drydep_config%diagnostic_species_id)
allocate(this%drydep_config%diagnostic_species_id(this%drydep_config%n_diagnostic_species))
! Map each diagnostic species name to its index in species_names
do i = 1, this%drydep_config%n_diagnostic_species
found_species = .false.
do j = 1, this%drydep_config%n_species
if (trim(this%drydep_config%diagnostic_species(i)) == trim(this%drydep_config%species_names(j))) then
this%drydep_config%diagnostic_species_id(i) = j
found_species = .true.
exit
end if
end do
if (.not. found_species) then
write(error_msg, '(A,A,A)') "Diagnostic species '", &
trim(this%drydep_config%diagnostic_species(i)), &
"' not found in process species list"
call error_handler%report_error(error_not_found, error_msg, rc)
!return !do not return and the diagnostics for this unspecified species will be zero in the output
end if
end do
end subroutine map_diagnostic_species_indices
end module drydepcommon_mod