diff --git a/doc/ChangeLog b/doc/ChangeLog index b08a0987..c5457571 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,59 @@ + +=============================================================== + +Tag name: +Originator(s): cacraig +Date: Dec 24, 2024 +One-line Summary: Complete Zhang McFarlane conversion to CCPP +Github PR URL: + +This PR fixes the following NCAR/atmospheric_physics Github issues: +Add ccpp'ized ZM : https://github.com/ESCOMP/atmospheric_physics/issues/66 + +Code reviewed by: + +List all existing files that have been added (A), modified (M), or deleted (D), +and describe the changes: +A schemes/cloud_fraction/cloud_fraction_fice.F90 +A schemes/cloud_fraction/cloud_fraction_fice.meta +A schemes/sima_diagnostics/zm_convr_tendency_diagnostics.F90 +A schemes/sima_diagnostics/zm_convr_tendency_diagnostics.meta +A schemes/sima_diagnostics/zm_diagnostics.F90 +A schemes/sima_diagnostics/zm_diagnostics.meta +A schemes/sima_diagnostics/zm_evap_tendency_diagnostics.F90 +A schemes/sima_diagnostics/zm_evap_tendency_diagnostics.meta +A schemes/sima_diagnostics/zm_momtran_tendency_diagnostics.F90 +A schemes/sima_diagnostics/zm_momtran_tendency_diagnostics.meta +A schemes/sima_diagnostics/zm_tendency_diagnostics.F90 +A schemes/sima_diagnostics/zm_tendency_diagnostics.meta +A schemes/utilities/to_be_ccppized_temporary.F90 +A schemes/utilities/to_be_ccppized_temporary.meta +A schemes/zhang_mcfarlane/set_deep_conv_fluxes_to_general.F90 +A schemes/zhang_mcfarlane/set_deep_conv_fluxes_to_general.meta +A schemes/zhang_mcfarlane/set_general_conv_fluxes_to_deep.F90 +A schemes/zhang_mcfarlane/set_general_conv_fluxes_to_deep.meta +M schemes/zhang_mcfarlane/zm_conv_convtran.F90 +M schemes/zhang_mcfarlane/zm_conv_convtran.meta +M schemes/zhang_mcfarlane/zm_conv_evap.F90 +M schemes/zhang_mcfarlane/zm_conv_evap.meta +M schemes/zhang_mcfarlane/zm_conv_momtran.F90 +M schemes/zhang_mcfarlane/zm_conv_momtran.meta +M schemes/zhang_mcfarlane/zm_convr.F90 +M schemes/zhang_mcfarlane/zm_convr.meta +A schemes/zhang_mcfarlane/zm_convr_namelist.xml +A suites/suite_zhang_mcfarlane.xml +M test/test_schemes/initialize_constituents.F90 +A to_be_ccppized/error_messages.F90 +A to_be_ccppized/namelist_utils.F90 +A to_be_ccppized/units.F90 +A to_be_ccppized/wv_sat_methods.F90 +A to_be_ccppized/wv_saturation.F90 + +List and Describe any test failures: + +Summarize any changes to answers: + +=============================================================== =============================================================== Tag name: atmos_phys0_07_000 diff --git a/doc/NamesNotInDictionary.txt b/doc/NamesNotInDictionary.txt index 99c2e48b..fa672759 100644 --- a/doc/NamesNotInDictionary.txt +++ b/doc/NamesNotInDictionary.txt @@ -1,14 +1,20 @@ ####################### Date/time of when script was run: -2024-12-16 11:19:41.130567 +2024-12-24 13:15:46.877558 ####################### Non-dictionary standard names found in the following metadata files: -------------------------- -atmospheric_physics/schemes/sima_diagnostics/check_energy_gmean_diagnostics.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/test/test_schemes/initialize_constituents.meta + + - dynamic_constituents_for_initialize_constituents + +-------------------------- + +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/sima_diagnostics/check_energy_gmean_diagnostics.meta - flag_for_energy_global_means_output - global_mean_heating_rate_correction_for_energy_conservation @@ -17,30 +23,57 @@ atmospheric_physics/schemes/sima_diagnostics/check_energy_gmean_diagnostics.meta -------------------------- -atmospheric_physics/schemes/sima_diagnostics/check_energy_diagnostics.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/sima_diagnostics/zm_convr_tendency_diagnostics.meta - - cumulative_total_energy_boundary_flux_using_physics_energy_formula - - cumulative_total_water_boundary_flux - - ratio_of_specific_heat_of_air_used_in_physics_energy_formula_to_specific_heat_of_air_used_in_dycore_energy_formula - - specific_heat_of_air_used_in_dycore - - vertically_integrated_total_energy_at_end_of_physics_timestep - - vertically_integrated_total_energy_using_dycore_energy_formula - - vertically_integrated_total_energy_using_physics_energy_formula - - vertically_integrated_total_water + - tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water -------------------------- -atmospheric_physics/schemes/sima_diagnostics/sima_state_diagnostics.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/sima_diagnostics/sima_state_diagnostics.meta - air_pressure_at_interface - air_pressure_of_dry_air_at_interface + - geopotential_height_wrt_surface_at_interface - ln_air_pressure_at_interface - ln_air_pressure_of_dry_air_at_interface - surface_air_pressure -------------------------- -atmospheric_physics/schemes/sima_diagnostics/tropopause_diagnostics.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/sima_diagnostics/zm_diagnostics.meta + + - atmosphere_convective_mass_flux_due_to_deep_convection + - atmosphere_downdraft_convective_mass_flux_for_deep_convection_for_convective_columns + - atmosphere_updraft_convective_mass_flux_for_deep_convection_for_convective_columns + - detrainment_of_cloud_liquid_due_to_deep_convection + - frozen_precipitation_flux_at_interface_due_to_deep_convection + - horizontal_index_of_convective_columns_for_deep_convection_for_convective_columns + - in_cloud_eastward_wind_in_downdraft_due_to_deep_convection + - in_cloud_eastward_wind_in_updraft_due_to_deep_convection + - in_cloud_northward_wind_in_downdraft_due_to_deep_convection + - in_cloud_northward_wind_in_updraft_due_to_deep_convection + - lwe_precipitation_rate_at_surface_due_to_deep_convection + - precipitation_flux_at_interface_due_to_deep_convection + - surface_air_pressure + - tendency_of_eastward_wind_due_to_zhang_mcfarlane_deep_convective_downdraft_pressure_gradient_term + - tendency_of_eastward_wind_due_to_zhang_mcfarlane_deep_convective_updraft_pressure_gradient_term + - tendency_of_frozen_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection + - tendency_of_northward_wind_due_to_zhang_mcfarlane_deep_convective_downdraft_pressure_gradient_term + - tendency_of_northward_wind_due_to_zhang_mcfarlane_deep_convective_updraft_pressure_gradient_term + - tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection + - vertical_index_at_top_of_deep_convection_for_convective_columns + - vertical_index_of_deep_convection_launch_level_for_convective_columns + - zhang_mcfarlane_convective_available_potential_energy + +-------------------------- + +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/sima_diagnostics/zm_tendency_diagnostics.meta + + - ccpp_constituent_tendencies + +-------------------------- + +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/sima_diagnostics/tropopause_diagnostics.meta - tropopause_air_pressure - tropopause_air_pressure_from_climatological_method @@ -68,37 +101,42 @@ atmospheric_physics/schemes/sima_diagnostics/tropopause_diagnostics.meta -------------------------- -atmospheric_physics/schemes/tj2016/tj2016_precip.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/sima_diagnostics/check_energy_diagnostics.meta - - gas_constant_of_water_vapor - - lwe_large_scale_precipitation_rate_at_surface - - ratio_of_water_vapor_to_dry_air_molecular_weights - - sum_of_sigma_pressure_hybrid_coordinate_a_coefficient_and_sigma_pressure_hybrid_coordinate_b_coefficient + - cumulative_total_energy_boundary_flux_using_physics_energy_formula + - cumulative_total_water_boundary_flux + - ratio_of_specific_heat_of_air_used_in_physics_energy_formula_to_specific_heat_of_air_used_in_dycore_energy_formula + - specific_heat_of_air_used_in_dycore + - vertically_integrated_total_energy_at_end_of_physics_timestep + - vertically_integrated_total_energy_using_dycore_energy_formula + - vertically_integrated_total_energy_using_physics_energy_formula + - vertically_integrated_total_water -------------------------- -atmospheric_physics/schemes/tj2016/tj2016_sfc_pbl_hs.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/sima_diagnostics/zm_evap_tendency_diagnostics.meta - - air_pressure_at_interface - - eddy_heat_diffusivity - - eddy_momentum_diffusivity - - gas_constant_of_water_vapor - - ln_air_pressure_at_interface - - pi_constant - - ratio_of_water_vapor_to_dry_air_molecular_weights - - sum_of_sigma_pressure_hybrid_coordinate_a_coefficient_and_sigma_pressure_hybrid_coordinate_b_coefficient - - surface_air_pressure - - surface_eastward_wind_stress - - surface_evaporation_rate - - surface_northward_wind_stress - - surface_upward_sensible_heat_flux - - tendency_of_air_temperature_due_to_diabatic_heating - - tendency_of_air_temperature_due_to_vertical_diffusion - - tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water_due_to_vertical_diffusion + - tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_evaporation_and_melting_of_frozen_precipitation_due_to_deep_convection + - tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_production_due_to_deep_convection + - tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water + +-------------------------- + +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/musica/musica_ccpp.meta + + - blackbody_temperature_at_surface + - cloud_area_fraction + - dynamic_constituents_for_musica_ccpp + - earth_sun_distance + - extraterrestrial_radiation_flux + - geopotential_height_wrt_surface_at_interface + - photolysis_wavelength_grid_interfaces + - solar_zenith_angle + - surface_albedo_due_to_UV_and_VIS_direct -------------------------- -atmospheric_physics/schemes/dry_adiabatic_adjust/dadadj.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/dry_adiabatic_adjust/dadadj.meta - air_pressure_at_interface - binary_indicator_for_dry_adiabatic_adjusted_grid_cell @@ -108,7 +146,61 @@ atmospheric_physics/schemes/dry_adiabatic_adjust/dadadj.meta -------------------------- -atmospheric_physics/schemes/zhang_mcfarlane/zm_conv_momtran.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/utilities/geopotential_temp.meta + + - air_pressure_at_interface + - geopotential_height_wrt_surface_at_interface + - ln_air_pressure_at_interface + +-------------------------- + +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/utilities/physics_tendency_updaters.meta + + - ccpp_constituent_tendencies + +-------------------------- + +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/tropopause_find/tropopause_find.meta + + - air_pressure_at_interface + - fill_value_for_diagnostic_output + - fractional_calendar_days_on_end_of_current_timestep + - geopotential_height_wrt_surface_at_interface + - pi_constant + - ratio_of_dry_air_gas_constant_to_specific_heat_of_dry_air_at_constant_pressure + - tropopause_air_pressure + - tropopause_air_pressure_from_chemical_method + - tropopause_air_pressure_from_climatological_method + - tropopause_air_pressure_from_cold_point_method + - tropopause_air_pressure_from_hybrid_stobie_linoz_with_climatological_backup_method + - tropopause_air_pressure_from_lapse_rate_method + - tropopause_air_pressure_from_tropopause_climatology_dataset + - tropopause_air_temperature + - tropopause_air_temperature_from_chemical_method + - tropopause_air_temperature_from_climatological_method + - tropopause_air_temperature_from_cold_point_method + - tropopause_air_temperature_from_hybrid_stobie_linoz_with_climatological_backup_method + - tropopause_air_temperature_from_lapse_rate_method + - tropopause_calendar_days_from_tropopause_climatology + - tropopause_geopotential_height_wrt_surface + - tropopause_geopotential_height_wrt_surface_from_chemical_method + - tropopause_geopotential_height_wrt_surface_from_climatological_method + - tropopause_geopotential_height_wrt_surface_from_cold_point_method + - tropopause_geopotential_height_wrt_surface_from_hybrid_stobie_linoz_with_climatological_backup_method + - tropopause_geopotential_height_wrt_surface_from_lapse_rate_method + - tropopause_vertical_layer_index + - tropopause_vertical_layer_index_from_chemical_method + - tropopause_vertical_layer_index_from_climatological_method + - tropopause_vertical_layer_index_from_cold_point_method + - tropopause_vertical_layer_index_from_hybrid_stobie_linoz_with_climatological_backup_method + - tropopause_vertical_layer_index_from_hybrid_stobie_linoz_with_climatological_backup_method_for_chemistry + - tropopause_vertical_layer_index_from_lapse_rate_method + - vertical_layer_index_lower_bound_from_hybrid_stobie_linoz_with_climatological_backup_method_for_linearized_ozone_chemistry + - vertical_layer_index_lower_bound_from_hybrid_stobie_linoz_with_climatological_backup_method_for_stratospheric_chemistry + +-------------------------- + +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/zhang_mcfarlane/zm_conv_momtran.meta - atmosphere_detrainment_convective_mass_flux_for_deep_convection_for_convective_columns - atmosphere_downdraft_convective_mass_flux_for_deep_convection_for_convective_columns @@ -116,14 +208,16 @@ atmospheric_physics/schemes/zhang_mcfarlane/zm_conv_momtran.meta - atmosphere_updraft_convective_mass_flux_for_deep_convection_for_convective_columns - atmosphere_updraft_entrainment_convective_mass_flux_for_deep_convection_for_convective_columns - current_timestep_number - - eastward_and_northward_winds_in_deep_convective_downdrafts? - - enter_name - - flag_for_zhang_mcfarlane_deep_momentum_transport? + - flag_for_momentum_transport_by_zhang_mcfarlane_deep_convection_scheme - horizontal_index_of_convective_columns_for_deep_convection_for_convective_columns - - maximum_number_of_grid_cells_with_deep_convection? - - minimum_number_of_grid_cells_with_deep_convection? - - momentum_downward_transport_parameter_for_zhang_mcfarlane? - - momentum_upward_transport_parameter_for_zhang_mcfarlane? + - in_cloud_eastward_wind_in_downdraft_due_to_deep_convection + - in_cloud_eastward_wind_in_updraft_due_to_deep_convection + - in_cloud_northward_wind_in_downdraft_due_to_deep_convection + - in_cloud_northward_wind_in_updraft_due_to_deep_convection + - index_of_first_column_of_gathered_deep_convection_arrays + - index_of_last_column_of_gathered_deep_convection_arrays + - momentum_transport_parameter_for_vertical_pressure_gradient_force_for_downdraft_for_zhang_mcfarlane_deep_convection_scheme + - momentum_transport_parameter_for_vertical_pressure_gradient_force_for_updraft_for_zhang_mcfarlane_deep_convection_scheme - pressure_thickness_for_deep_convection_for_convective_columns - pressure_thickness_for_subcloud_layer_for_deep_convection_for_convective_columns - tendency_of_eastward_wind_due_to_zhang_mcfarlane_deep_convective_downdraft_pressure_gradient_term @@ -131,135 +225,174 @@ atmospheric_physics/schemes/zhang_mcfarlane/zm_conv_momtran.meta - tendency_of_northward_wind_due_to_zhang_mcfarlane_deep_convective_downdraft_pressure_gradient_term - tendency_of_northward_wind_due_to_zhang_mcfarlane_deep_convective_updraft_pressure_gradient_term - vertical_index_at_top_of_deep_convection_for_convective_columns - - vertical_index_of_deep_conveciton_launch_level_for_convective_columns - --------------------------- - -atmospheric_physics/schemes/zhang_mcfarlane/zm_conv_evap.meta - - - - - cloud_area_fraction - - flag_for_zhang_mcfarlane_convective_organization_parameterization? - - freezing_point_of_water? - - frozen_precipitation_mass_flux_at_interface_due_to_deep_convection? - - heating_rate - - latent_heat_of_fusion_of_water_at_0c? - - latent_heat_of_vaporization_of_water_at_0c? - - lwe_frozen_precipitation_rate_at_surface_due_to_deep_convection - - lwe_precipitation_rate_at_surface_due_to_deep_convection - - precipitation_mass_flux_at_interface_due_to_deep_convection? - - pressure_thickness - - specific_heat_of_dry_air_at_constant_pressure? - - tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_melt? - - tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_production_in_deep_convection? - - tendency_of_frozen_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection? - - tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection? - - tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection_excluding_subcloud_evaporation - - tendency_of_water_vapor_mixing_ratio_wrt_moist_air and_condensed_water? - - tunable_evaporation_efficiency_for_land_in_zhang_mcfarlane_deep_convection_scheme? - - tunable_evaporation_efficiency_in_zhang_mcfarlane_deep_convection_scheme? + - vertical_index_of_deep_convection_launch_level_for_convective_columns -------------------------- -atmospheric_physics/schemes/zhang_mcfarlane/zm_convr.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/zhang_mcfarlane/zm_convr.meta - air_pressure_at_interface - - atmosphere_convective_mass_flux_due_to all_convection? + - atmosphere_convective_mass_flux_due_to_deep_convection - atmosphere_detrainment_convective_mass_flux_for_deep_convection_for_convective_columns - atmosphere_downdraft_convective_mass_flux_for_deep_convection_for_convective_columns - atmosphere_downdraft_entrainment_convective_mass_flux_for_deep_convection_for_convective_columns - atmosphere_updraft_convective_mass_flux_for_deep_convection_for_convective_columns - atmosphere_updraft_entrainment_convective_mass_flux_for_deep_convection_for_convective_columns - - condensate_to_precipitation_autoconversion_coefficient_over_land_for_zhang_mcfarlane? - - condensate_to_precipitation_autoconversion_coefficient_over_ocean_for_zhang_mcfarlane? - - convective_available_potential_energy? + - cape_threshold_for_zhang_mcfarlane_deep_convection_scheme + - cloud_condensate_to_precipitation_autoconversion_coefficient_over_land_for_zhang_mcfarlane_deep_convection_scheme + - cloud_condensate_to_precipitation_autoconversion_coefficient_over_ocean_for_zhang_mcfarlane_deep_convection_scheme - convective_temperature_perturbation_due_to_pbl_eddies - - deep_convection_triggering_cape_threshold_for_zhang_mcfarlane? - - deep_convective_adjustment_timescale_for_zhang_mcfarlane? - - deep_convective_entrainment_rate_for_zhang_mcfarlane? - - deep_convective_organization_amount? - - deep_convective_organization_amount_at_single_vertical_layer_spread_over_whole_column? - - deep_convective_organization_amount_for_zhang_mcfarlane? - - detrained_cloud_droplet_number_concentration_from_deep_convection? - - detrained_cloud_ice_crystal_number_concentration_from_deep_convection? + - deep_convective_adjustment_timescale_for_zhang_mcfarlane_deep_convection_scheme - detrainment_mass_flux_due_to_deep_convection - detrainment_of_cloud_ice_due_to_deep_convection - detrainment_of_cloud_liquid_due_to_deep_convection - - enter_name - - flag_for_no_deep_convection_in_pbl? - - freezing_point_of_water? - - gas_constant_of_water_vapor? + - entrainment_rate_for_cape_for_zhang_mcfarlane_deep_convection_scheme + - flag_for_no_deep_convection_in_pbl + - flag_for_well_mixed_pbl_parcel_property_for_zhang_mcfarlane_deep_convection_scheme + - freezing_point_of_water + - gas_constant_of_water_vapor + - geopotential_height_wrt_surface_at_interface - horizontal_index_of_convective_columns_for_deep_convection_for_convective_columns - in_cloud_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water_due_to_deep_convection - - initial_parcel_property_as_function_of_well-mixed_pbl_for_zhang_mcfarlane? - - latent_heat_of_fusion_of_water_at_0c? - - latent_heat_of_vaporization_of_water_at_0c? + - index_of_last_column_of_gathered_deep_convection_arrays + - latent_heat_of_fusion_of_water_at_0c - lwe_precipitation_rate_at_surface_due_to_deep_convection - - momentum_downward_transport_parameter_for_zhang_mcfarlane? - - momentum_upward_transport_parameter_for_zhang_mcfarlane? - - number_of_negative_buoyancy_regions_allowed_before_convection_top_for_zhang_mcfarlane? - - parcel_temperature_perturbation_for_zhang_mcfarlane? + - momentum_transport_parameter_for_vertical_pressure_gradient_force_for_downdraft_for_zhang_mcfarlane_deep_convection_scheme + - momentum_transport_parameter_for_vertical_pressure_gradient_force_for_updraft_for_zhang_mcfarlane_deep_convection_scheme + - number_of_negative_buoyancy_layers_allowed_before_convection_top_for_zhang_mcfarlane_deep_convection_scheme + - parcel_temperature_perturbation_for_zhang_mcfarlane_deep_convection_scheme - pressure_thickness_for_deep_convection_for_convective_columns - pressure_thickness_for_subcloud_layer_for_deep_convection_for_convective_columns - - ratio_of_h2o_to_dry_air_molecular_weights? - - specific_heat_of_water_vapor_at_constant_pressure? - - tendency_of_deep_convective_organization_amount? + - ratio_of_water_vapor_to_dry_air_molecular_weights + - reference_pressure_at_interface + - specific_heat_of_liquid_water_at_constant_pressure + - specific_heat_of_water_vapor_at_constant_pressure - tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection_excluding_subcloud_evaporation - tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water - - tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water_due_to_cloud_condensation_minus_precipitation_evaporation_in_deep_convection? - - tunable_evaporation_efficiency_for_land_in zhang_mcfarlane_deep_convection_scheme? - - tunable_evaporation_efficiency_in_zhang_mcfarlane_deep_convection_scheme? + - tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water_from_cloud_condensation_minus_precipitation_evaporation_due_to_deep_convection + - tunable_evaporation_efficiency_over_land_for_zhang_mcfarlane_deep_convection_scheme + - tunable_evaporation_efficiency_over_ocean_for_zhang_mcfarlane_deep_convection_scheme - vertical_index_at_top_of_deep_convection_for_convective_columns - vertical_index_of_deep_convection_launch_level_for_convective_columns - - vertical_interface_index_of_deep_convection_height_limit? - vertically_integrated_cloud_ice_tendency_due_to_all_convection_to_be_applied_later_in_time_loop - vertically_integrated_cloud_liquid_tendency_due_to_all_convection_to_be_applied_later_in_time_loop + - zhang_mcfarlane_convective_available_potential_energy -------------------------- -atmospheric_physics/schemes/zhang_mcfarlane/zm_conv_convtran.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/zhang_mcfarlane/set_general_conv_fluxes_to_deep.meta + + - frozen_precipitation_flux_at_interface_due_to_convection + - frozen_precipitation_flux_at_interface_due_to_deep_convection + - lwe_frozen_precipitation_rate_at_surface_due_to_convection + - lwe_frozen_precipitation_rate_at_surface_due_to_deep_convection + - lwe_precipitation_rate_at_surface_due_to_convection + - lwe_precipitation_rate_at_surface_due_to_deep_convection + - precipitation_flux_at_interface_due_to_convection + - precipitation_flux_at_interface_due_to_deep_convection + - tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_evaporation_and_melting_of_frozen_precipitation_due_to_convection + - tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_evaporation_and_melting_of_frozen_precipitation_due_to_deep_convection + - tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_production_due_to_convection + - tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_production_due_to_deep_convection + - tendency_of_frozen_precipitation_wrt_moist_air_and_condensed_water_due_to_convection + - tendency_of_frozen_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection + - tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_convection + - tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_convection_excluding_subcloud_evaporation + - tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection + - tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection_excluding_subcloud_evaporation + +-------------------------- + +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/zhang_mcfarlane/zm_conv_convtran.meta - atmosphere_detrainment_convective_mass_flux_for_deep_convection_for_convective_columns - atmosphere_downdraft_convective_mass_flux_for_deep_convection_for_convective_columns - atmosphere_downdraft_entrainment_convective_mass_flux_for_deep_convection_for_convective_columns - atmosphere_updraft_convective_mass_flux_for_deep_convection_for_convective_columns - atmosphere_updraft_entrainment_convective_mass_flux_for_deep_convection_for_convective_columns + - ccpp_constituent_tendencies - current_timestep_number - - flag_for_zhang_mcfarlane_deep_convective_transport? + - flag_for_tracer_transport_by_zhang_mcfarlane_deep_scheme - fraction_of_water_insoluble_convectively_transported_species - horizontal_index_of_convective_columns_for_deep_convection_for_convective_columns - - maximum_number_of_grid_cells_with_deep_convection? - - minimum_number_of_grid_cells_with_deep_convection? + - index_of_first_column_of_gathered_deep_convection_arrays + - index_of_last_column_of_gathered_deep_convection_arrays - pressure_thickness_for_deep_convection_for_convective_columns - pressure_thickness_for_subcloud_layer_for_deep_convection_for_convective_columns - - pressure_thickness_of_dry_air_for_deep_convection_for_convective_columns? - - tendency_of_ccpp_constituents? - vertical_index_at_top_of_deep_convection_for_convective_columns - - vertical_index_of_deep_conveciton_launch_level_for_convective_columns + - vertical_index_of_deep_convection_launch_level_for_convective_columns -------------------------- -atmospheric_physics/schemes/utilities/geopotential_temp.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/zhang_mcfarlane/set_deep_conv_fluxes_to_general.meta - - air_pressure_at_interface - - ln_air_pressure_at_interface + - lwe_precipitation_rate_at_surface_due_to_convection + - lwe_precipitation_rate_at_surface_due_to_deep_convection + - tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_convection_excluding_subcloud_evaporation + - tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection_excluding_subcloud_evaporation -------------------------- -atmospheric_physics/schemes/utilities/physics_tendency_updaters.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/zhang_mcfarlane/zm_conv_evap.meta - - ccpp_constituent_tendencies + - cloud_area_fraction + - freezing_point_of_water + - frozen_precipitation_flux_at_interface_due_to_convection + - latent_heat_of_fusion_of_water_at_0c + - lwe_frozen_precipitation_rate_at_surface_due_to_convection + - lwe_precipitation_rate_at_surface_due_to_convection + - mass_fraction_of_snow_content_within_stratiform_cloud + - precipitation_flux_at_interface_due_to_convection + - tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_evaporation_and_melting_of_frozen_precipitation_due_to_convection + - tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_production_due_to_convection + - tendency_of_frozen_precipitation_wrt_moist_air_and_condensed_water_due_to_convection + - tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_convection + - tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_convection_excluding_subcloud_evaporation + - tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water + - tunable_evaporation_efficiency_over_land_for_zhang_mcfarlane_deep_convection_scheme + - tunable_evaporation_efficiency_over_ocean_for_zhang_mcfarlane_deep_convection_scheme + +-------------------------- + +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/cloud_fraction/cloud_fraction_fice.meta + + - freezing_point_of_water + - index_of_pressure_at_troposphere_cloud_top + - mass_fraction_of_ice_content_within_stratiform_cloud + - mass_fraction_of_snow_content_within_stratiform_cloud + +-------------------------- + +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/check_energy/dycore_energy_consistency_adjust.meta + + - flag_for_dycore_energy_consistency_adjustment + - ratio_of_specific_heat_of_air_used_in_physics_energy_formula_to_specific_heat_of_air_used_in_dycore_energy_formula + +-------------------------- + +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/check_energy/check_energy_scaling.meta + + - ratio_of_specific_heat_of_air_used_in_physics_energy_formula_to_specific_heat_of_air_used_in_dycore_energy_formula + - specific_heat_of_air_used_in_dycore -------------------------- -atmospheric_physics/schemes/check_energy/check_energy_save_teout.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/check_energy/check_energy_fix.meta + + - air_pressure_at_interface + - global_mean_heating_rate_correction_for_energy_conservation + - net_sensible_heat_flux_through_top_and_bottom_of_atmosphere_column + +-------------------------- + +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/check_energy/check_energy_save_teout.meta - vertically_integrated_total_energy_at_end_of_physics_timestep - vertically_integrated_total_energy_using_dycore_energy_formula -------------------------- -atmospheric_physics/schemes/check_energy/check_energy_chng.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/check_energy/check_energy_chng.meta - air_pressure_of_dry_air_at_interface - air_temperature_at_start_of_physics_timestep @@ -287,7 +420,7 @@ atmospheric_physics/schemes/check_energy/check_energy_chng.meta -------------------------- -atmospheric_physics/schemes/check_energy/check_energy_zero_fluxes.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/check_energy/check_energy_zero_fluxes.meta - net_liquid_and_lwe_ice_fluxes_through_top_and_bottom_of_atmosphere_column - net_lwe_ice_fluxes_through_top_and_bottom_of_atmosphere_column @@ -296,29 +429,7 @@ atmospheric_physics/schemes/check_energy/check_energy_zero_fluxes.meta -------------------------- -atmospheric_physics/schemes/check_energy/dycore_energy_consistency_adjust.meta - - - flag_for_dycore_energy_consistency_adjustment - - ratio_of_specific_heat_of_air_used_in_physics_energy_formula_to_specific_heat_of_air_used_in_dycore_energy_formula - --------------------------- - -atmospheric_physics/schemes/check_energy/check_energy_scaling.meta - - - ratio_of_specific_heat_of_air_used_in_physics_energy_formula_to_specific_heat_of_air_used_in_dycore_energy_formula - - specific_heat_of_air_used_in_dycore - --------------------------- - -atmospheric_physics/schemes/check_energy/check_energy_fix.meta - - - air_pressure_at_interface - - global_mean_heating_rate_correction_for_energy_conservation - - net_sensible_heat_flux_through_top_and_bottom_of_atmosphere_column - --------------------------- - -atmospheric_physics/schemes/check_energy/check_energy_gmean/check_energy_gmean.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/check_energy/check_energy_gmean/check_energy_gmean.meta - air_pressure_at_interface - global_mean_air_pressure_at_top_of_atmosphere_model @@ -332,60 +443,32 @@ atmospheric_physics/schemes/check_energy/check_energy_gmean/check_energy_gmean.m -------------------------- -atmospheric_physics/schemes/tropopause_find/tropopause_find.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/tj2016/tj2016_precip.meta - - air_pressure_at_interface - - fill_value_for_diagnostic_output - - fractional_calendar_days_on_end_of_current_timestep - - pi_constant - - ratio_of_dry_air_gas_constant_to_specific_heat_of_dry_air_at_constant_pressure - - tropopause_air_pressure - - tropopause_air_pressure_from_chemical_method - - tropopause_air_pressure_from_climatological_method - - tropopause_air_pressure_from_cold_point_method - - tropopause_air_pressure_from_hybrid_stobie_linoz_with_climatological_backup_method - - tropopause_air_pressure_from_lapse_rate_method - - tropopause_air_pressure_from_tropopause_climatology_dataset - - tropopause_air_temperature - - tropopause_air_temperature_from_chemical_method - - tropopause_air_temperature_from_climatological_method - - tropopause_air_temperature_from_cold_point_method - - tropopause_air_temperature_from_hybrid_stobie_linoz_with_climatological_backup_method - - tropopause_air_temperature_from_lapse_rate_method - - tropopause_calendar_days_from_tropopause_climatology - - tropopause_geopotential_height_wrt_surface - - tropopause_geopotential_height_wrt_surface_from_chemical_method - - tropopause_geopotential_height_wrt_surface_from_climatological_method - - tropopause_geopotential_height_wrt_surface_from_cold_point_method - - tropopause_geopotential_height_wrt_surface_from_hybrid_stobie_linoz_with_climatological_backup_method - - tropopause_geopotential_height_wrt_surface_from_lapse_rate_method - - tropopause_vertical_layer_index - - tropopause_vertical_layer_index_from_chemical_method - - tropopause_vertical_layer_index_from_climatological_method - - tropopause_vertical_layer_index_from_cold_point_method - - tropopause_vertical_layer_index_from_hybrid_stobie_linoz_with_climatological_backup_method - - tropopause_vertical_layer_index_from_hybrid_stobie_linoz_with_climatological_backup_method_for_chemistry - - tropopause_vertical_layer_index_from_lapse_rate_method - - vertical_layer_index_lower_bound_from_hybrid_stobie_linoz_with_climatological_backup_method_for_linearized_ozone_chemistry - - vertical_layer_index_lower_bound_from_hybrid_stobie_linoz_with_climatological_backup_method_for_stratospheric_chemistry - --------------------------- - -atmospheric_physics/schemes/musica/musica_ccpp.meta - - - blackbody_temperature_at_surface - - cloud_area_fraction - - dynamic_constituents_for_musica_ccpp - - earth_sun_distance - - extraterrestrial_radiation_flux - - photolysis_wavelength_grid_interfaces - - solar_zenith_angle - - surface_albedo_due_to_UV_and_VIS_direct + - gas_constant_of_water_vapor + - lwe_large_scale_precipitation_rate_at_surface + - ratio_of_water_vapor_to_dry_air_molecular_weights + - sum_of_sigma_pressure_hybrid_coordinate_a_coefficient_and_sigma_pressure_hybrid_coordinate_b_coefficient -------------------------- -atmospheric_physics/test/test_schemes/initialize_constituents.meta +/home/cacraig/cam_sima_zm4/src/physics/ncar_ccpp/schemes/tj2016/tj2016_sfc_pbl_hs.meta - - dynamic_constituents_for_initialize_constituents + - air_pressure_at_interface + - eddy_heat_diffusivity + - eddy_momentum_diffusivity + - gas_constant_of_water_vapor + - ln_air_pressure_at_interface + - pi_constant + - ratio_of_water_vapor_to_dry_air_molecular_weights + - sum_of_sigma_pressure_hybrid_coordinate_a_coefficient_and_sigma_pressure_hybrid_coordinate_b_coefficient + - surface_air_pressure + - surface_eastward_wind_stress + - surface_evaporation_rate + - surface_northward_wind_stress + - surface_upward_sensible_heat_flux + - tendency_of_air_temperature_due_to_diabatic_heating + - tendency_of_air_temperature_due_to_vertical_diffusion + - tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water_due_to_vertical_diffusion ####################### diff --git a/schemes/cloud_fraction/cloud_fraction_fice.F90 b/schemes/cloud_fraction/cloud_fraction_fice.F90 new file mode 100644 index 00000000..7c102ece --- /dev/null +++ b/schemes/cloud_fraction/cloud_fraction_fice.F90 @@ -0,0 +1,89 @@ +module cloud_fraction_fice + + use ccpp_kinds, only: kind_phys + implicit none + +contains + +!================================================================================================ + +!=============================================================================== +!> \section arg_table_cloud_fraction_fice_run Argument Table +!! \htmlinclude cloud_fraction_fice_run.html +!! + subroutine cloud_fraction_fice_run(ncol, t, tmelt, top_lev, pver, fice, fsnow) +! +! Compute the fraction of the total cloud water which is in ice phase. +! The fraction depends on temperature only. +! This is the form that was used for radiation, the code came from cldefr originally +! +! Author: B. A. Boville Sept 10, 2002 +! modified: PJR 3/13/03 (added fsnow to ascribe snow production for convection ) +!----------------------------------------------------------------------- + +! Arguments + integer, intent(in) :: ncol ! number of active columns + real(kind_phys), intent(in) :: t(:,:) ! temperature + real(kind_phys), intent(in) :: tmelt ! freezing point of water + integer, intent(in) :: top_lev + integer, intent(in) :: pver + + real(kind_phys), intent(out) :: fice(:,:) ! Fractional ice content within cloud + real(kind_phys), intent(out) :: fsnow(:,:) ! Fractional snow content for convection + +! Local variables + real(kind_phys) :: tmax_fice ! max temperature for cloud ice formation + real(kind_phys) :: tmin_fice ! min temperature for cloud ice formation + real(kind_phys) :: tmax_fsnow ! max temperature for transition to convective snow + real(kind_phys) :: tmin_fsnow ! min temperature for transition to convective snow + + integer :: i,k ! loop indexes + +!----------------------------------------------------------------------- + + tmax_fice = tmelt - 10._kind_phys ! max temperature for cloud ice formation + tmin_fice = tmax_fice - 30._kind_phys ! min temperature for cloud ice formation + tmax_fsnow = tmelt ! max temperature for transition to convective snow + tmin_fsnow = tmelt - 5._kind_phys ! min temperature for transition to convective snow + + fice(:,:top_lev-1) = 0._kind_phys + fsnow(:,:top_lev-1) = 0._kind_phys + +! Define fractional amount of cloud that is ice + do k=top_lev,pver + do i=1,ncol + +! If warmer than tmax then water phase + if (t(i,k) > tmax_fice) then + fice(i,k) = 0.0_kind_phys + +! If colder than tmin then ice phase + else if (t(i,k) < tmin_fice) then + fice(i,k) = 1.0_kind_phys + +! Otherwise mixed phase, with ice fraction decreasing linearly from tmin to tmax + else + fice(i,k) =(tmax_fice - t(i,k)) / (tmax_fice - tmin_fice) + end if + +! snow fraction partitioning + +! If warmer than tmax then water phase + if (t(i,k) > tmax_fsnow) then + fsnow(i,k) = 0.0_kind_phys + +! If colder than tmin then ice phase + else if (t(i,k) < tmin_fsnow) then + fsnow(i,k) = 1.0_kind_phys + +! Otherwise mixed phase, with ice fraction decreasing linearly from tmin to tmax + else + fsnow(i,k) =(tmax_fsnow - t(i,k)) / (tmax_fsnow - tmin_fsnow) + end if + + end do + end do + + end subroutine cloud_fraction_fice_run + +end module cloud_fraction_fice diff --git a/schemes/cloud_fraction/cloud_fraction_fice.meta b/schemes/cloud_fraction/cloud_fraction_fice.meta new file mode 100644 index 00000000..25e97945 --- /dev/null +++ b/schemes/cloud_fraction/cloud_fraction_fice.meta @@ -0,0 +1,49 @@ +[ccpp-table-properties] + name = cloud_fraction_fice + type = scheme + +[ccpp-arg-table] + name = cloud_fraction_fice_run + type = scheme +[ ncol ] + standard_name = horizontal_loop_extent + units = count + type = integer + dimensions = () + intent = in +[ t ] + standard_name = air_temperature + units = K + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ tmelt ] + standard_name = freezing_point_of_water + units = K + type = real | kind = kind_phys + dimensions = () + intent = in +[ top_lev ] + standard_name = index_of_pressure_at_troposphere_cloud_top + units = index + type = integer + dimensions = () + intent = in +[ pver ] + standard_name = vertical_layer_dimension + units = count + type = integer + dimensions = () + intent = in +[ fice ] + standard_name = mass_fraction_of_ice_content_within_stratiform_cloud + units = fraction + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = out +[ fsnow ] + standard_name = mass_fraction_of_snow_content_within_stratiform_cloud + units = fraction + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = out diff --git a/schemes/sima_diagnostics/zm_convr_tendency_diagnostics.F90 b/schemes/sima_diagnostics/zm_convr_tendency_diagnostics.F90 new file mode 100644 index 00000000..181465da --- /dev/null +++ b/schemes/sima_diagnostics/zm_convr_tendency_diagnostics.F90 @@ -0,0 +1,70 @@ +module zm_convr_tendency_diagnostics + use ccpp_kinds, only: kind_phys + + implicit none + private + save + + public :: zm_convr_tendency_diagnostics_init ! init routine + public :: zm_convr_tendency_diagnostics_run ! main routine + +CONTAINS + + !> \section arg_table_zm_convr_tendency_diagnostics_init Argument Table + !! \htmlinclude zm_convr_tendency_diagnostics_init.html + subroutine zm_convr_tendency_diagnostics_init(errmsg, errflg) + use cam_history, only: history_add_field + use cam_history_support, only: horiz_only + + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + ! Local variables: + + errmsg = '' + errflg = 0 + + call history_add_field ('ZMDT', 'T tendency - Zhang-McFarlane moist convection', 'lev', 'avg', 'K s-1') + call history_add_field ('ZMDQ', 'Q tendency - Zhang-McFarlane moist convection', 'lev', 'avg', 'kg kg-1 s-1') + + end subroutine zm_convr_tendency_diagnostics_init + + !> \section arg_table_zm_convr_tendency_diagnostics_run Argument Table + !! \htmlinclude zm_convr_tendency_diagnostics_run.html + subroutine zm_convr_tendency_diagnostics_run(ncol, pver, cpair, heat, qtnd, errmsg, errflg) + + use cam_history, only: history_out_field + + !------------------------------------------------ + ! Input / output parameters + !------------------------------------------------ + integer, intent(in) :: ncol + integer, intent(in) :: pver + + real(kind_phys), intent(in) :: cpair + real(kind_phys), intent(in) :: heat(:,:) + real(kind_phys), intent(in) :: qtnd(:,:) + + ! CCPP error handling variables + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + + real(kind_phys) :: ftem(ncol,pver) + + integer :: index_cldliq + + errmsg = '' + errflg = 0 + + ftem(:,:) = 0._kind_phys + + ftem(:ncol,:pver) = heat(:ncol,:pver)/cpair + call history_out_field('ZMDT ', ftem) + call history_out_field('ZMDQ ', qtnd) + + end subroutine zm_convr_tendency_diagnostics_run + + !======================================================================= + +end module zm_convr_tendency_diagnostics diff --git a/schemes/sima_diagnostics/zm_convr_tendency_diagnostics.meta b/schemes/sima_diagnostics/zm_convr_tendency_diagnostics.meta new file mode 100644 index 00000000..e23eb1bb --- /dev/null +++ b/schemes/sima_diagnostics/zm_convr_tendency_diagnostics.meta @@ -0,0 +1,70 @@ +[ccpp-table-properties] + name = zm_convr_tendency_diagnostics + type = scheme + +[ccpp-arg-table] + name = zm_convr_tendency_diagnostics_init + type = scheme +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out + +[ccpp-arg-table] + name = zm_convr_tendency_diagnostics_run + type = scheme +[ ncol ] + standard_name = horizontal_loop_extent + units = count + type = integer + dimensions = () + intent = in +[ pver ] + standard_name = vertical_layer_dimension + units = count + type = integer + dimensions = () + intent = in +[ cpair ] + standard_name = specific_heat_of_dry_air_at_constant_pressure + units = J kg-1 K-1 + type = real | kind = kind_phys + dimensions = () + intent = in +[ heat ] + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure + units = J kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ qtnd ] + standard_name = tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out + diff --git a/schemes/sima_diagnostics/zm_diagnostics.F90 b/schemes/sima_diagnostics/zm_diagnostics.F90 new file mode 100644 index 00000000..58cea81f --- /dev/null +++ b/schemes/sima_diagnostics/zm_diagnostics.F90 @@ -0,0 +1,206 @@ +module zm_diagnostics + use ccpp_kinds, only: kind_phys + + implicit none + private + save + + public :: zm_diagnostics_init ! init routine + public :: zm_diagnostics_run ! main routine + +CONTAINS + + !> \section arg_table_zm_diagnostics_init Argument Table + !! \htmlinclude zm_diagnostics_init.html + subroutine zm_diagnostics_init(errmsg, errflg) + use cam_history, only: history_add_field + use cam_history_support, only: horiz_only + + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + ! Local variables: + + errmsg = '' + errflg = 0 + + call history_add_field ('PRECZ', 'lwe_precipitation_rate_at_surface_due_to_deep_convection_due_to_Zhang-McFarlane', & + horiz_only, 'avg', 'm s-1') + call history_add_field ('ZMFLXPRC', 'precipitation_flux_at_interface_due_to_deep_convection', 'ilev', 'avg', 'kg m-2 s-1') + call history_add_field ('ZMFLXSNW', 'frozen_precipitation_flux_at_interface_due_to_deep_convection', & + 'ilev', 'avg', 'kg m-2 s-1') + call history_add_field ('ZMNTPRPD', 'tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection', & + 'lev', 'avg', 'kg kg-1 s-1') + call history_add_field ('ZMNTSNPD', & + 'tendency_of_frozen_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection', & + 'lev', 'avg', 'kg kg-1 s-1') + + call history_add_field ('CMFMC_DP', 'Convection mass flux from ZM deep ', 'ilev', 'avg', 'kg m-2 s-1') + call history_add_field ('PRECCDZM', 'lwe_precipitation_rate_at_surface_due_to_deep_convection', horiz_only, 'avg', 'm s-1') + + call history_add_field ('PCONVB', 'convection base pressure', horiz_only , 'avg', 'Pa' ) + call history_add_field ('PCONVT', 'convection top pressure', horiz_only , 'avg', 'Pa' ) + + call history_add_field ('CAPE', 'zhang_mcfarlane_convective_available_potential_energy', horiz_only, 'avg', 'J kg-1') + call history_add_field ('FREQZM', 'Fractional occurance of ZM convection', horiz_only , 'avg', 'fraction') + + call history_add_field ('ZMMU', 'ZM convection updraft mass flux', 'lev', 'avg', 'kg m-2 s-1') + call history_add_field ('ZMMD', 'ZM convection downdraft mass flux', 'lev', 'avg', 'kg m-2 s-1') + + call history_add_field ('ZMUPGU',& + 'tendency_of_eastward_wind_due_to_zhang_mcfarlane_deep_convective_updraft_pressure_gradient_term',& + 'lev', 'avg', 'm s-2') + call history_add_field ('ZMUPGD',& + 'tendency_of_eastward_wind_due_to_zhang_mcfarlane_deep_convective_downdraft_pressure_gradient_term',& + 'lev', 'avg', 'm s-2') + call history_add_field ('ZMVPGU',& + 'tendency_of_northward_wind_due_to_zhang_mcfarlane_deep_convective_updraft_pressure_gradient_term',& + 'lev', 'avg', 'm s-2') + call history_add_field ('ZMVPGD',& + 'tendency_of_northward_wind_due_to_zhang_mcfarlane_deep_convective_downdraft_pressure_gradient_term',& + 'lev', 'avg', 'm s-2') + + call history_add_field ('ZMICUU', 'in_cloud_eastward_wind_in_updraft_due_to_deep_convection', 'lev', 'avg', 'm s-1') + call history_add_field ('ZMICUD', 'in_cloud_eastward_wind_in_downdraft_due_to_deep_convection', 'lev', 'avg', 'm s-1') + call history_add_field ('ZMICVU', 'in_cloud_northward_wind_in_updraft_due_to_deep_convection', 'lev', 'avg', 'm s-1') + call history_add_field ('ZMICVD', 'in_cloud_northward_wind_in_downdraft_due_to_deep_convection', 'lev', 'avg', 'm s-1') + + call history_add_field ('DLFZM', 'detrainment_of_cloud_liquid_due_to_deep_convection', 'lev', 'avg','kg kg-1 s-1 ') + + + end subroutine zm_diagnostics_init + + !> \section arg_table_zm_diagnostics_run Argument Table + !! \htmlinclude zm_diagnostics_run.html + subroutine zm_diagnostics_run(ncol, pver, pverp, ideep, cpair, prec, cape, gravit, mu, md, & + dlf, ps, pap, maxg, jt, flxprec, flxsnow, ntprprd, ntsnprd, pguallu, pguallv, & + pgdallu, pgdallv, icwuu, icwuv, icwdu, icwdv, mcon, errmsg, errflg) + + use cam_history, only: history_out_field + + !------------------------------------------------ + ! Input / output parameters + !------------------------------------------------ + integer, intent(in) :: ncol + integer, intent(in) :: pver + integer, intent(in) :: pverp + integer, intent(in) :: ideep(:) + + real(kind_phys), intent(in) :: cpair + real(kind_phys), intent(in) :: prec(:) + real(kind_phys), intent(in) :: cape(:) + real(kind_phys), intent(in) :: gravit + real(kind_phys), intent(in) :: mu(:,:) + real(kind_phys), intent(in) :: md(:,:) + real(kind_phys), intent(in) :: dlf(:,:) + real(kind_phys), intent(in) :: ps(:) + real(kind_phys), intent(in) :: pap(:,:) + integer, intent(in) :: maxg(ncol) + integer, intent(in) :: jt(ncol) + real(kind_phys),intent(in) :: flxprec(:,:) + real(kind_phys),intent(in) :: flxsnow(:,:) + real(kind_phys),intent(in) :: ntprprd(:,:) + real(kind_phys),intent(in) :: ntsnprd(:,:) + real(kind_phys),intent(in) :: pguallu(:,:) + real(kind_phys),intent(in) :: pguallv(:,:) + real(kind_phys),intent(in) :: pgdallu(:,:) + real(kind_phys),intent(in) :: pgdallv(:,:) + real(kind_phys),intent(in) :: icwuu(:,:) + real(kind_phys),intent(in) :: icwuv(:,:) + real(kind_phys),intent(in) :: icwdu(:,:) + real(kind_phys),intent(in) :: icwdv(:,:) + + real(kind_phys),intent(inout) :: mcon(:,:) + + ! CCPP error handling variables + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + integer :: lengath ! number of columns with deep convection + + real(kind_phys) :: freqzm(ncol) + real(kind_phys) :: pcont(ncol) + real(kind_phys) :: pconb(ncol) + real(kind_phys) :: ftem(ncol,pver) + real(kind_phys) :: mconzm(ncol,pverp) + real(kind_phys) :: mu_out(ncol,pver) + real(kind_phys) :: md_out(ncol,pver) + + integer :: index_cldliq + integer i, ii, k + + errmsg = '' + errflg = 0 + + mu_out(:,:) = 0._kind_phys + md_out(:,:) = 0._kind_phys + + lengath = count(ideep > 0) + if (lengath > ncol) lengath = ncol ! should not happen, but force it to not be larger than ncol for safety sake + + call history_out_field('CAPE', cape) + + freqzm(:) = 0._kind_phys + do i = 1,lengath + freqzm(ideep(i)) = 1.0_kind_phys + end do + call history_out_field('FREQZM ',freqzm) + + mcon(:ncol,:pverp) = mcon(:ncol,:pverp) * 100._kind_phys/gravit + mconzm(:ncol,:pverp) = mcon(:ncol,:pverp) + + call history_out_field('CMFMC_DP', mconzm) + + + ! Store upward and downward mass fluxes in un-gathered arrays + ! + convert from mb/s to kg/m^2/s + do i=1,lengath + do k=1,pver + ii = ideep(i) + mu_out(ii,k) = mu(i,k) * 100._kind_phys/gravit + md_out(ii,k) = md(i,k) * 100._kind_phys/gravit + end do + end do + + call history_out_field('ZMMU', mu_out) + call history_out_field('ZMMD', md_out) + + call history_out_field('DLFZM' ,dlf) + + pcont(:ncol) = ps(:ncol) + pconb(:ncol) = ps(:ncol) + do i = 1,lengath + if (maxg(i).gt.jt(i)) then + pcont(ideep(i)) = pap(ideep(i),jt(i)) ! gathered array (or jctop ungathered) + pconb(ideep(i)) = pap(ideep(i),maxg(i))! gathered array + endif + end do + call history_out_field('PCONVT ',pcont) + call history_out_field('PCONVB ',pconb) + + call history_out_field('ZMFLXPRC', flxprec) + call history_out_field('ZMFLXSNW', flxsnow) + call history_out_field('ZMNTPRPD', ntprprd) + call history_out_field('ZMNTSNPD', ntsnprd) + +!CAM was outputting the exact same quantity to both fields + call history_out_field('PRECCDZM ',prec) + call history_out_field('PRECZ ', prec) + + ! Output apparent force from pressure gradient + call history_out_field('ZMUPGU', pguallu) + call history_out_field('ZMUPGD', pgdallu) + call history_out_field('ZMVPGU', pguallv) + call history_out_field('ZMVPGD', pgdallv) + + ! Output in-cloud winds + call history_out_field('ZMICUU', icwuu) + call history_out_field('ZMICUD', icwdu) + call history_out_field('ZMICVU', icwuv) + call history_out_field('ZMICVD', icwdv) + + end subroutine zm_diagnostics_run + + !======================================================================= + +end module zm_diagnostics diff --git a/schemes/sima_diagnostics/zm_diagnostics.meta b/schemes/sima_diagnostics/zm_diagnostics.meta new file mode 100644 index 00000000..c834f7d4 --- /dev/null +++ b/schemes/sima_diagnostics/zm_diagnostics.meta @@ -0,0 +1,213 @@ +[ccpp-table-properties] + name = zm_diagnostics + type = scheme + +[ccpp-arg-table] + name = zm_diagnostics_init + type = scheme +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out + +[ccpp-arg-table] + name = zm_diagnostics_run + type = scheme +[ ncol ] + standard_name = horizontal_loop_extent + units = count + type = integer + dimensions = () + intent = in +[ pver ] + standard_name = vertical_layer_dimension + units = count + type = integer + dimensions = () + intent = in +[ pverp ] + standard_name = vertical_interface_dimension + units = count + type = integer + dimensions = () + intent = in +[ ideep ] + standard_name = horizontal_index_of_convective_columns_for_deep_convection_for_convective_columns + units = index + type = integer + dimensions = (horizontal_loop_extent) + intent = in +[ cpair ] + standard_name = specific_heat_of_dry_air_at_constant_pressure + units = J kg-1 K-1 + type = real | kind = kind_phys + dimensions = () + intent = in +[ prec ] + standard_name = lwe_precipitation_rate_at_surface_due_to_deep_convection + units = m s-1 + type = real | kind = kind_phys + dimensions = (1:horizontal_loop_extent) + intent = in +[ cape ] + standard_name = zhang_mcfarlane_convective_available_potential_energy + units = J kg-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent) + intent = in +[ gravit ] + standard_name = standard_gravitational_acceleration + units = m s-2 + type = real | kind = kind_phys + dimensions = () + intent = in +[ mu ] + standard_name = atmosphere_updraft_convective_mass_flux_for_deep_convection_for_convective_columns + units = hPa s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ md ] + standard_name = atmosphere_downdraft_convective_mass_flux_for_deep_convection_for_convective_columns + units = hPa s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +#[ dif ] +# standard_name = detrainment_of_cloud_ice_due_to_deep_convection +# units = kg kg-1 s-1 +# type = real | kind = kind_phys +# dimensions = (horizontal_loop_extent,vertical_layer_dimension) +# intent = in +[ dlf ] + standard_name = detrainment_of_cloud_liquid_due_to_deep_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ ps ] + standard_name = surface_air_pressure + units = Pa + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent) + intent = in +[ pap ] + standard_name = air_pressure + units = Pa + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ maxg ] + standard_name = vertical_index_of_deep_convection_launch_level_for_convective_columns + units = index + type = integer + dimensions = (horizontal_loop_extent) + intent = in +[ jt ] + standard_name = vertical_index_at_top_of_deep_convection_for_convective_columns + units = index + type = integer + dimensions = (horizontal_loop_extent) + intent = in +[ flxprec ] + standard_name = precipitation_flux_at_interface_due_to_deep_convection + units = kg m-2 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_interface_dimension) + intent = in +[ flxsnow ] + standard_name = frozen_precipitation_flux_at_interface_due_to_deep_convection + units = kg m-2 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_interface_dimension) + intent = in +[ ntprprd ] + standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ ntsnprd ] + standard_name = tendency_of_frozen_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ pguallu ] + standard_name = tendency_of_eastward_wind_due_to_zhang_mcfarlane_deep_convective_updraft_pressure_gradient_term + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ pguallv ] + standard_name = tendency_of_northward_wind_due_to_zhang_mcfarlane_deep_convective_updraft_pressure_gradient_term + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ pgdallu ] + standard_name = tendency_of_eastward_wind_due_to_zhang_mcfarlane_deep_convective_downdraft_pressure_gradient_term + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ pgdallv ] + standard_name = tendency_of_northward_wind_due_to_zhang_mcfarlane_deep_convective_downdraft_pressure_gradient_term + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ icwuu ] + standard_name = in_cloud_eastward_wind_in_updraft_due_to_deep_convection + units = m s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ icwuv ] + standard_name = in_cloud_northward_wind_in_updraft_due_to_deep_convection + units = m s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ icwdu ] + standard_name = in_cloud_eastward_wind_in_downdraft_due_to_deep_convection + units = m s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ icwdv ] + standard_name = in_cloud_northward_wind_in_downdraft_due_to_deep_convection + units = m s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ mcon ] + standard_name = atmosphere_convective_mass_flux_due_to_deep_convection + units = hPa s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_interface_dimension) + intent = inout +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out diff --git a/schemes/sima_diagnostics/zm_evap_tendency_diagnostics.F90 b/schemes/sima_diagnostics/zm_evap_tendency_diagnostics.F90 new file mode 100644 index 00000000..450807bc --- /dev/null +++ b/schemes/sima_diagnostics/zm_evap_tendency_diagnostics.F90 @@ -0,0 +1,81 @@ +module zm_evap_tendency_diagnostics + use ccpp_kinds, only: kind_phys + + implicit none + private + save + + public :: zm_evap_tendency_diagnostics_init ! init routine + public :: zm_evap_tendency_diagnostics_run ! main routine + +CONTAINS + + !> \section arg_table_zm_evap_tendency_diagnostics_init Argument Table + !! \htmlinclude zm_evap_tendency_diagnostics_init.html + subroutine zm_evap_tendency_diagnostics_init(errmsg, errflg) + use cam_history, only: history_add_field + use cam_history_support, only: horiz_only + + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + ! Local variables: + + errmsg = '' + errflg = 0 + + call history_add_field ('ZMEIHEAT', 'Heating by ice and evaporation in ZM convection', 'lev', 'avg', 'W kg-1') + + call history_add_field ('EVAPTZM', 'T tendency - Evaporation/snow prod from Zhang convection', 'lev', 'avg', 'K s-1') + call history_add_field ('FZSNTZM', 'T tendency - Rain to snow conversion from Zhang convection', 'lev', 'avg', 'K s-1') + call history_add_field ('EVSNTZM', 'T tendency - Snow to rain prod from Zhang convection', 'lev', 'avg', 'K s-1') + call history_add_field ('EVAPQZM', 'Q tendency - Evaporation from Zhang-McFarlane moist convection', 'lev', 'avg', & + 'kg kg-1 s-1') + + end subroutine zm_evap_tendency_diagnostics_init + + !> \section arg_table_zm_evap_tendency_diagnostics_run Argument Table + !! \htmlinclude zm_evap_tendency_diagnostics_run.html + subroutine zm_evap_tendency_diagnostics_run(ncol, pver, cpair, tend_s_snwprd, tend_s_snwevmlt, qtnd, heat, errmsg, errflg) + + use cam_history, only: history_out_field + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t + !------------------------------------------------ + ! Input / output parameters + !------------------------------------------------ + integer, intent(in) :: ncol + integer, intent(in) :: pver + real(kind_phys), intent(in) :: cpair + real(kind_phys), intent(in) :: tend_s_snwprd(:,:) + real(kind_phys), intent(in) :: tend_s_snwevmlt(:,:) + real(kind_phys), intent(in) :: qtnd(:,:) + real(kind_phys), intent(in) :: heat(:,:) + + ! CCPP error handling variables + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + integer :: lengath ! number of columns with deep convection + integer :: const_idx + character(len=256) :: standard_name + + real(kind_phys) :: ftem(ncol,pver) + + errmsg = '' + + errflg = 0 + + ftem(:ncol,:pver) = heat(:ncol,:pver)/cpair + call history_out_field('EVAPTZM ',ftem) + ftem(:ncol,:pver) = tend_s_snwprd (:ncol,:pver)/cpair + call history_out_field('FZSNTZM ',ftem) + ftem(:ncol,:pver) = tend_s_snwevmlt(:ncol,:pver)/cpair + call history_out_field('EVSNTZM ',ftem) + call history_out_field('EVAPQZM ',qtnd) + call history_out_field('ZMEIHEAT', heat) + + end subroutine zm_evap_tendency_diagnostics_run + + !======================================================================= + +end module zm_evap_tendency_diagnostics diff --git a/schemes/sima_diagnostics/zm_evap_tendency_diagnostics.meta b/schemes/sima_diagnostics/zm_evap_tendency_diagnostics.meta new file mode 100644 index 00000000..09fa27ab --- /dev/null +++ b/schemes/sima_diagnostics/zm_evap_tendency_diagnostics.meta @@ -0,0 +1,81 @@ +[ccpp-table-properties] + name = zm_evap_tendency_diagnostics + type = scheme + +[ccpp-arg-table] + name = zm_evap_tendency_diagnostics_init + type = scheme +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out + +[ccpp-arg-table] + name = zm_evap_tendency_diagnostics_run + type = scheme +[ ncol ] + standard_name = horizontal_loop_extent + units = count + type = integer + dimensions = () + intent = in +[ pver ] + standard_name = vertical_layer_dimension + units = count + type = integer + dimensions = () + intent = in +[ cpair ] + standard_name = specific_heat_of_dry_air_at_constant_pressure + units = J kg-1 K-1 + type = real | kind = kind_phys + dimensions = () + intent = in +[ tend_s_snwprd ] + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_production_due_to_deep_convection + units = J kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ tend_s_snwevmlt ] + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_evaporation_and_melting_of_frozen_precipitation_due_to_deep_convection + units = J kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ qtnd ] + standard_name = tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ heat ] + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure + units = J kg-1 s-1 + type = real | kind = kind_phys + dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + intent = in +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out diff --git a/schemes/sima_diagnostics/zm_momtran_tendency_diagnostics.F90 b/schemes/sima_diagnostics/zm_momtran_tendency_diagnostics.F90 new file mode 100644 index 00000000..7000d2fa --- /dev/null +++ b/schemes/sima_diagnostics/zm_momtran_tendency_diagnostics.F90 @@ -0,0 +1,67 @@ +module zm_momtran_tendency_diagnostics + use ccpp_kinds, only: kind_phys + + implicit none + private + save + + public :: zm_momtran_tendency_diagnostics_init ! init routine + public :: zm_momtran_tendency_diagnostics_run ! main routine + +CONTAINS + + !> \section arg_table_zm_momtran_tendency_diagnostics_init Argument Table + !! \htmlinclude zm_momtran_tendency_diagnostics_init.html + subroutine zm_momtran_tendency_diagnostics_init(errmsg, errflg) + use cam_history, only: history_add_field + use cam_history_support, only: horiz_only + + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + ! Local variables: + + errmsg = '' + errflg = 0 + + call history_add_field ('ZMMTT', 'T tendency - ZM convective momentum transport', 'lev', 'avg', 'K s-1') + call history_add_field ('ZMMTU', 'U tendency - ZM convective momentum transport', 'lev', 'avg', 'm s-2') + call history_add_field ('ZMMTV', 'V tendency - ZM convective momentum transport', 'lev', 'avg', 'm s-2') + + end subroutine zm_momtran_tendency_diagnostics_init + + !> \section arg_table_zm_momtran_tendency_diagnostics_run Argument Table + !! \htmlinclude zm_momtran_tendency_diagnostics_run.html + subroutine zm_momtran_tendency_diagnostics_run(ncol, pver, cpair, windu_tend, windv_tend, seten, errmsg, errflg) + + use cam_history, only: history_out_field + !------------------------------------------------ + ! Input / output parameters + !------------------------------------------------ + integer, intent(in) :: ncol + integer, intent(in) :: pver + real(kind_phys), intent(in) :: cpair + real(kind_phys), intent(in) :: windu_tend(:,:) + real(kind_phys), intent(in) :: windv_tend(:,:) + real(kind_phys), intent(in) :: seten(:,:) + + ! CCPP error handling variables + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + real(kind_phys) :: ftem(ncol,pver) + + errmsg = '' + errflg = 0 + + call history_out_field('ZMMTU', windu_tend) + call history_out_field('ZMMTV', windv_tend) + + ftem(:ncol,:pver) = seten(:ncol,:pver)/cpair + call history_out_field('ZMMTT', ftem) + + end subroutine zm_momtran_tendency_diagnostics_run + + !======================================================================= + +end module zm_momtran_tendency_diagnostics diff --git a/schemes/sima_diagnostics/zm_momtran_tendency_diagnostics.meta b/schemes/sima_diagnostics/zm_momtran_tendency_diagnostics.meta new file mode 100644 index 00000000..8000522e --- /dev/null +++ b/schemes/sima_diagnostics/zm_momtran_tendency_diagnostics.meta @@ -0,0 +1,75 @@ +[ccpp-table-properties] + name = zm_momtran_tendency_diagnostics + type = scheme + +[ccpp-arg-table] + name = zm_momtran_tendency_diagnostics_init + type = scheme +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out + +[ccpp-arg-table] + name = zm_momtran_tendency_diagnostics_run + type = scheme +[ ncol ] + standard_name = horizontal_loop_extent + units = count + type = integer + dimensions = () + intent = in +[ pver ] + standard_name = vertical_layer_dimension + units = count + type = integer + dimensions = () + intent = in +[ cpair ] + standard_name = specific_heat_of_dry_air_at_constant_pressure + units = J kg-1 K-1 + type = real | kind = kind_phys + dimensions = () + intent = in +[ windu_tend ] + standard_name = tendency_of_eastward_wind + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ windv_tend ] + standard_name = tendency_of_northward_wind + units = m s-2 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ seten ] + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure + units = J kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out diff --git a/schemes/sima_diagnostics/zm_tendency_diagnostics.F90 b/schemes/sima_diagnostics/zm_tendency_diagnostics.F90 new file mode 100644 index 00000000..ea24cacb --- /dev/null +++ b/schemes/sima_diagnostics/zm_tendency_diagnostics.F90 @@ -0,0 +1,82 @@ +module zm_tendency_diagnostics + use ccpp_kinds, only: kind_phys + + implicit none + private + save + + public :: zm_tendency_diagnostics_init ! init routine + public :: zm_tendency_diagnostics_run ! main routine + +CONTAINS + + !> \section arg_table_zm_tendency_diagnostics_init Argument Table + !! \htmlinclude zm_tendency_diagnostics_init.html + subroutine zm_tendency_diagnostics_init(errmsg, errflg) + use cam_history, only: history_add_field + use cam_history_support, only: horiz_only + + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + ! Local variables: + + errmsg = '' + errflg = 0 + + call history_add_field ('ZMDICE', 'Cloud ice tendency - Zhang-McFarlane convection', 'lev', 'avg', 'kg kg-1 s-1') + call history_add_field ('ZMDLIQ', 'Cloud liq tendency - Zhang-McFarlane convection', 'lev', 'avg', 'kg kg-1 s-1') + + end subroutine zm_tendency_diagnostics_init + + !> \section arg_table_zm_tendency_diagnostics_run Argument Table + !! \htmlinclude zm_tendency_diagnostics_run.html + subroutine zm_tendency_diagnostics_run(ncol, pver, pverp, const_props, dqdt, errmsg, errflg) + + use cam_history, only: history_out_field + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t + !------------------------------------------------ + ! Input / output parameters + !------------------------------------------------ + integer, intent(in) :: ncol + integer, intent(in) :: pver + integer, intent(in) :: pverp + type(ccpp_constituent_prop_ptr_t), intent(in) :: const_props(:) + real(kind_phys), intent(in) :: dqdt(:,:,:) ! Tracer tendency array (ncol,pver,ncnst) + + ! CCPP error handling variables + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + integer :: lengath ! number of columns with deep convection + integer :: const_idx + character(len=256) :: standard_name + + real(kind_phys) :: ftem(ncol,pver) + + errmsg = '' + errflg = 0 + + do const_idx = 1, size(const_props) + call const_props(const_idx)%standard_name(standard_name, errflg, errmsg) + + ! Use the regular constituent names, as the location in the dqdt array does not match the constituent ordering in the + ! constituent properties + + select case (trim(standard_name)) + + case('cloud_liquid_water_mixing_ratio_wrt_moist_air_and_condensed_water') + call history_out_field('ZMDLIQ', dqdt(:,:,const_idx)) + + case('cloud_ice_mixing_ratio_wrt_moist_air_and_condensed_water') + call history_out_field('ZMDICE', dqdt(:,:,const_idx)) + + end select + + end do + + end subroutine zm_tendency_diagnostics_run + + !======================================================================= + +end module zm_tendency_diagnostics diff --git a/schemes/sima_diagnostics/zm_tendency_diagnostics.meta b/schemes/sima_diagnostics/zm_tendency_diagnostics.meta new file mode 100644 index 00000000..cca5cd56 --- /dev/null +++ b/schemes/sima_diagnostics/zm_tendency_diagnostics.meta @@ -0,0 +1,69 @@ +[ccpp-table-properties] + name = zm_tendency_diagnostics + type = scheme + +[ccpp-arg-table] + name = zm_tendency_diagnostics_init + type = scheme +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out + +[ccpp-arg-table] + name = zm_tendency_diagnostics_run + type = scheme +[ ncol ] + standard_name = horizontal_loop_extent + units = count + type = integer + dimensions = () + intent = in +[ pver ] + standard_name = vertical_layer_dimension + units = count + type = integer + dimensions = () + intent = in +[ pverp ] + standard_name = vertical_interface_dimension + units = count + type = integer + dimensions = () + intent = in +[ const_props ] + standard_name = ccpp_constituent_properties + units = None + type = ccpp_constituent_prop_ptr_t + dimensions = (number_of_ccpp_constituents) + intent = in +[ dqdt ] + standard_name = ccpp_constituent_tendencies + units = none + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension,number_of_ccpp_constituents) + intent = in +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out diff --git a/schemes/utilities/to_be_ccppized_temporary.F90 b/schemes/utilities/to_be_ccppized_temporary.F90 new file mode 100644 index 00000000..e87d221e --- /dev/null +++ b/schemes/utilities/to_be_ccppized_temporary.F90 @@ -0,0 +1,29 @@ +module to_be_ccppized_temporary +! This module is a TEMPORARY place to put calls to initialization routines which have not yet +! been CCPP'ized, and the run methods are being called directly in CCPP'ized routines. + +! Once a module has been CCPP'ized, then the call in this routine needs to be removed + +implicit none + +contains + +!> \section arg_table_to_be_ccppized_temporary_init Argument Table +!! \htmlinclude to_be_ccppized_temporary_init.html +!! +subroutine to_be_ccppized_temporary_init(errmsg, errflg) + + use wv_saturation, only: wv_sat_init + + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + errmsg = ' ' + errflg = 0 + + call wv_sat_init() + +end subroutine to_be_ccppized_temporary_init + +end module to_be_ccppized_temporary + diff --git a/schemes/utilities/to_be_ccppized_temporary.meta b/schemes/utilities/to_be_ccppized_temporary.meta new file mode 100644 index 00000000..bceeb3f7 --- /dev/null +++ b/schemes/utilities/to_be_ccppized_temporary.meta @@ -0,0 +1,22 @@ +[ccpp-table-properties] + name = to_be_ccppized_temporary + type = scheme + dependencies = ../../to_be_ccppized/wv_saturation.F90 +[ccpp-arg-table] + name = to_be_ccppized_temporary_init + type = scheme +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out + diff --git a/schemes/zhang_mcfarlane/set_deep_conv_fluxes_to_general.F90 b/schemes/zhang_mcfarlane/set_deep_conv_fluxes_to_general.F90 new file mode 100644 index 00000000..bd76369f --- /dev/null +++ b/schemes/zhang_mcfarlane/set_deep_conv_fluxes_to_general.F90 @@ -0,0 +1,26 @@ +module set_deep_conv_fluxes_to_general + + use ccpp_kinds, only: kind_phys + + implicit none + +contains + +!=============================================================================== +!> \section arg_table_set_deep_conv_fluxes_to_general_run Argument Table +!! \htmlinclude set_deep_conv_fluxes_to_general_run.html +!! + + subroutine set_deep_conv_fluxes_to_general_run(prec_gen, prec_dp, prdprec_gen, prdprec_dp) + + real(kind_phys), intent(out) :: prec_gen(:) + real(kind_phys), intent(in) :: prec_dp(:) + real(kind_phys), intent(out) :: prdprec_gen(:,:) + real(kind_phys), intent(in) :: prdprec_dp(:,:) + + prec_gen = prec_dp + prdprec_gen = prdprec_dp + + end subroutine set_deep_conv_fluxes_to_general_run + +end module set_deep_conv_fluxes_to_general diff --git a/schemes/zhang_mcfarlane/set_deep_conv_fluxes_to_general.meta b/schemes/zhang_mcfarlane/set_deep_conv_fluxes_to_general.meta new file mode 100644 index 00000000..ecf21332 --- /dev/null +++ b/schemes/zhang_mcfarlane/set_deep_conv_fluxes_to_general.meta @@ -0,0 +1,31 @@ +[ccpp-table-properties] + name = set_deep_conv_fluxes_to_general + type = scheme + +[ccpp-arg-table] + name = set_deep_conv_fluxes_to_general_run + type = scheme +[ prec_gen ] + standard_name = lwe_precipitation_rate_at_surface_due_to_convection + units = m s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent) + intent = out +[ prec_dp ] + standard_name = lwe_precipitation_rate_at_surface_due_to_deep_convection + units = m s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent) + intent = in +[ prdprec_gen ] + standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_convection_excluding_subcloud_evaporation + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = out +[ prdprec_dp ] + standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection_excluding_subcloud_evaporation + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent, vertical_layer_dimension) + intent = in diff --git a/schemes/zhang_mcfarlane/set_general_conv_fluxes_to_deep.F90 b/schemes/zhang_mcfarlane/set_general_conv_fluxes_to_deep.F90 new file mode 100644 index 00000000..2bd023f2 --- /dev/null +++ b/schemes/zhang_mcfarlane/set_general_conv_fluxes_to_deep.F90 @@ -0,0 +1,46 @@ +module set_general_conv_fluxes_to_deep + + use ccpp_kinds, only: kind_phys + + implicit none + +contains + +!=============================================================================== +!> \section arg_table_set_general_conv_fluxes_to_deep_run Argument Table +!! \htmlinclude set_general_conv_fluxes_to_deep_run.html +!! + + subroutine set_general_conv_fluxes_to_deep_run(tend_s_snwprd_gen, tend_s_snwprd_dp, tend_s_snwevmlt_gen, tend_s_snwevmlt_dp, & + prec_gen, prec_dp, snow_gen, snow_dp, ntprprd_gen, ntprprd_dp, ntsnprd_gen, ntsnprd_dp, & + flxprec_gen, flxprec_dp, flxsnow_gen, flxsnow_dp) + + real(kind_phys), intent(in) :: tend_s_snwprd_gen(:,:) + real(kind_phys), intent(out) :: tend_s_snwprd_dp(:,:) + real(kind_phys), intent(in) :: tend_s_snwevmlt_gen(:,:) + real(kind_phys), intent(out) :: tend_s_snwevmlt_dp(:,:) + real(kind_phys), intent(in) :: prec_gen(:) + real(kind_phys), intent(out) :: prec_dp(:) + real(kind_phys), intent(in) :: snow_gen(:) + real(kind_phys), intent(out) :: snow_dp(:) + real(kind_phys), intent(in) :: ntprprd_gen(:,:) + real(kind_phys), intent(out) :: ntprprd_dp(:,:) + real(kind_phys), intent(in) :: ntsnprd_gen(:,:) + real(kind_phys), intent(out) :: ntsnprd_dp(:,:) + real(kind_phys), intent(in) :: flxprec_gen(:,:) + real(kind_phys), intent(out) :: flxprec_dp(:,:) + real(kind_phys), intent(in) :: flxsnow_gen(:,:) + real(kind_phys), intent(out) :: flxsnow_dp(:,:) + + tend_s_snwprd_dp = tend_s_snwprd_gen + tend_s_snwevmlt_dp = tend_s_snwevmlt_gen + prec_dp = prec_gen + snow_dp = snow_gen + ntprprd_dp = ntprprd_gen + ntsnprd_dp = ntsnprd_gen + flxprec_dp = flxprec_gen + flxsnow_dp = flxsnow_gen + + end subroutine set_general_conv_fluxes_to_deep_run + +end module set_general_conv_fluxes_to_deep diff --git a/schemes/zhang_mcfarlane/set_general_conv_fluxes_to_deep.meta b/schemes/zhang_mcfarlane/set_general_conv_fluxes_to_deep.meta new file mode 100644 index 00000000..b06351dc --- /dev/null +++ b/schemes/zhang_mcfarlane/set_general_conv_fluxes_to_deep.meta @@ -0,0 +1,103 @@ +[ccpp-table-properties] + name = set_general_conv_fluxes_to_deep + type = scheme + +[ccpp-arg-table] + name = set_general_conv_fluxes_to_deep_run + type = scheme +[ tend_s_snwprd_gen ] + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_production_due_to_convection + units = J kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ tend_s_snwprd_dp ] + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_production_due_to_deep_convection + units = J kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = out +[ tend_s_snwevmlt_gen ] + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_evaporation_and_melting_of_frozen_precipitation_due_to_convection + units = J kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ tend_s_snwevmlt_dp ] + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_evaporation_and_melting_of_frozen_precipitation_due_to_deep_convection + units = J kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = out +[ prec_gen ] + standard_name = lwe_precipitation_rate_at_surface_due_to_convection + units = m s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent) + intent = in +[ prec_dp ] + standard_name = lwe_precipitation_rate_at_surface_due_to_deep_convection + units = m s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent) + intent = out +[ snow_gen ] + standard_name = lwe_frozen_precipitation_rate_at_surface_due_to_convection + units = m s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent) + intent = in +[ snow_dp ] + standard_name = lwe_frozen_precipitation_rate_at_surface_due_to_deep_convection + units = m s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent) + intent = out +[ ntprprd_gen ] + standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ ntprprd_dp ] + standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = out +[ ntsnprd_gen ] + standard_name = tendency_of_frozen_precipitation_wrt_moist_air_and_condensed_water_due_to_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ ntsnprd_dp ] + standard_name = tendency_of_frozen_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = out +[ flxprec_gen ] + standard_name = precipitation_flux_at_interface_due_to_convection + units = kg m-2 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_interface_dimension) + intent = in +[ flxprec_dp ] + standard_name = precipitation_flux_at_interface_due_to_deep_convection + units = kg m-2 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_interface_dimension) + intent = out +[ flxsnow_gen ] + standard_name = frozen_precipitation_flux_at_interface_due_to_convection + units = kg m-2 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_interface_dimension) + intent = in +[ flxsnow_dp ] + standard_name = frozen_precipitation_flux_at_interface_due_to_deep_convection + units = kg m-2 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_interface_dimension) + intent = out diff --git a/schemes/zhang_mcfarlane/zm_conv_convtran.F90 b/schemes/zhang_mcfarlane/zm_conv_convtran.F90 index 56988ebe..ed3123a2 100644 --- a/schemes/zhang_mcfarlane/zm_conv_convtran.F90 +++ b/schemes/zhang_mcfarlane/zm_conv_convtran.F90 @@ -9,11 +9,41 @@ module zm_conv_convtran ! ! PUBLIC: interfaces ! + public zm_conv_convtran_init public zm_conv_convtran_run ! convective transport contains +!=============================================================================== +!> \section arg_table_zm_conv_convtran_init Argument Table +!! \htmlinclude zm_conv_convtran_init.html +!! +subroutine zm_conv_convtran_init(qprops, ncnst, doconvtran, errmsg, errflg) + +use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t + + implicit none + + type(ccpp_constituent_prop_ptr_t), intent(in) :: qprops(:) + integer, intent(in) :: ncnst ! number of tracers to transport + + logical, intent(out) :: doconvtran(:) ! flag for doing convective transport (ncnst) + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + + + integer :: q_index + + errmsg = '' + errflg = 0 + + do q_index=1,ncnst + call qprops(q_index)%is_water_species(doconvtran(q_index), errflg, errmsg) + if (errflg /= 0) return + end do + +end subroutine zm_conv_convtran_init !=============================================================================== !> \section arg_table_zm_conv_convtran_run Argument Table !! \htmlinclude zm_conv_convtran_run.html @@ -22,7 +52,9 @@ subroutine zm_conv_convtran_run(ncol, pver, & doconvtran,q ,ncnst ,mu ,md , & du ,eu ,ed ,dp ,dsubcld , & jt ,mx ,ideep ,il1g ,il2g , & - nstep ,fracis ,dqdt ,dpdry) + nstep ,fracis ,dqdt ,dpdry ,const_metadata, & + scheme_name, errmsg, errflg) + !----------------------------------------------------------------------- ! ! Purpose: @@ -37,8 +69,8 @@ subroutine zm_conv_convtran_run(ncol, pver, & ! Author: P. Rasch ! !----------------------------------------------------------------------- -! CACNOTE - replace with CCPP constituents - use constituents, only: cnst_get_type_byind + use ccpp_constituent_prop_mod, only: ccpp_constituent_prop_ptr_t + implicit none !----------------------------------------------------------------------- @@ -68,6 +100,12 @@ subroutine zm_conv_convtran_run(ncol, pver, & real(kind_phys), intent(in) :: dpdry(:,:) ! Delta pressure between interfaces (ncol,pver) + + type(ccpp_constituent_prop_ptr_t), intent(in) :: const_metadata(:) + character(len=40), intent(out) :: scheme_name + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + ! input/output real(kind_phys), intent(out) :: dqdt(:,:,:) ! Tracer tendency array (ncol,pver,ncnst) @@ -84,6 +122,8 @@ subroutine zm_conv_convtran_run(ncol, pver, & integer ktm ! Highest altitude index of cloud top integer m ! Work index + logical :: is_dry + real(kind_phys) cabv ! Mix ratio of constituent above real(kind_phys) cbel ! Mix ratio of constituent below real(kind_phys) cdifr ! Normalized diff between cabv and cbel @@ -109,8 +149,14 @@ subroutine zm_conv_convtran_run(ncol, pver, & real(kind_phys) total(ncol) real(kind_phys) negadt,qtmp + character(len=256) :: standard_name + !----------------------------------------------------------------------- ! + scheme_name = "zm_conv_convtran_run" + errmsg = '' + errflg = 0 + small = 1.e-36_kind_phys ! mbsth is the threshold below which we treat the mass fluxes as zero (in mb/s) mbsth = 1.e-15_kind_phys @@ -124,10 +170,18 @@ subroutine zm_conv_convtran_run(ncol, pver, & end do ! Loop ever each constituent - do m = 2, ncnst + dqdt(:,:,:) = 0._kind_phys + do m = 1, ncnst + + call const_metadata(m)%standard_name(standard_name) + if (standard_name == 'water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water') then + cycle + end if + if (doconvtran(m)) then - if (cnst_get_type_byind(m).eq.'dry') then + call const_metadata(m)%is_dry(is_dry, errflg, errmsg) + if (is_dry) then do k = 1,pver do i =il1g,il2g dptmp(i,k) = dpdry(i,k) @@ -270,8 +324,7 @@ subroutine zm_conv_convtran_run(ncol, pver, & end do end do -! Initialize to zero everywhere, then scatter tendency back to full array - dqdt(:,:,m) = 0._kind_phys +! Scatter tendency back to full array do k = 1,pver kp1 = min(pver,k+1) do i = il1g,il2g diff --git a/schemes/zhang_mcfarlane/zm_conv_convtran.meta b/schemes/zhang_mcfarlane/zm_conv_convtran.meta index c2b4a9b3..4f7c6cb1 100644 --- a/schemes/zhang_mcfarlane/zm_conv_convtran.meta +++ b/schemes/zhang_mcfarlane/zm_conv_convtran.meta @@ -2,6 +2,41 @@ name = zm_conv_convtran type = scheme +[ccpp-arg-table] + name = zm_conv_convtran_init + type = scheme +[ qprops ] + standard_name = ccpp_constituent_properties + units = None + type = ccpp_constituent_prop_ptr_t + dimensions = (number_of_ccpp_constituents) + intent = in +[ ncnst ] + standard_name = number_of_ccpp_constituents + units = count + type = integer + dimensions = () + intent = in +[ doconvtran ] + standard_name = flag_for_tracer_transport_by_zhang_mcfarlane_deep_scheme + units = flag + type = logical + dimensions = (number_of_ccpp_constituents) + intent = out +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out [ccpp-arg-table] name = zm_conv_convtran_run type = scheme @@ -18,17 +53,18 @@ dimensions = () intent = in [ doconvtran ] - standard_name = flag_for_zhang_mcfarlane_deep_convective_transport? + standard_name = flag_for_tracer_transport_by_zhang_mcfarlane_deep_scheme units = flag type = logical - dimensions = (1:number_of_ccpp_constituents) + dimensions = (number_of_ccpp_constituents) intent = in [ q ] standard_name = ccpp_constituents units = none type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension,1:number_of_ccpp_constituents) + dimensions = (horizontal_loop_extent,vertical_layer_dimension,number_of_ccpp_constituents) intent = in + advected = true [ ncnst ] standard_name = number_of_ccpp_constituents units = count @@ -37,73 +73,73 @@ intent = in [ mu ] standard_name = atmosphere_updraft_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = hPa s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ md ] standard_name = atmosphere_downdraft_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = hPa s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ du ] standard_name = atmosphere_detrainment_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ eu ] standard_name = atmosphere_updraft_entrainment_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ ed ] standard_name = atmosphere_downdraft_entrainment_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ dp ] standard_name = pressure_thickness_for_deep_convection_for_convective_columns units = hPa type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ dsubcld ] standard_name = pressure_thickness_for_subcloud_layer_for_deep_convection_for_convective_columns units = hPa type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in [ jt ] standard_name = vertical_index_at_top_of_deep_convection_for_convective_columns units = index type = integer - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in [ mx ] - standard_name = vertical_index_of_deep_conveciton_launch_level_for_convective_columns + standard_name = vertical_index_of_deep_convection_launch_level_for_convective_columns units = index type = integer - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in [ ideep ] standard_name = horizontal_index_of_convective_columns_for_deep_convection_for_convective_columns units = index type = integer - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in [ il1g ] - standard_name = minimum_number_of_grid_cells_with_deep_convection? - units = 1 + standard_name = index_of_first_column_of_gathered_deep_convection_arrays + units = index type = integer dimensions = () intent = in [ il2g ] - standard_name = maximum_number_of_grid_cells_with_deep_convection? - units = 1 + standard_name = index_of_last_column_of_gathered_deep_convection_arrays + units = index type = integer dimensions = () intent = in @@ -115,19 +151,46 @@ intent = in [ fracis ] standard_name = fraction_of_water_insoluble_convectively_transported_species - units = frac + units = fraction type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension,1:number_of_ccpp_constituents) + dimensions = (horizontal_loop_extent,vertical_layer_dimension,number_of_ccpp_constituents) intent = in [ dqdt ] - standard_name = tendency_of_ccpp_constituents? + standard_name = ccpp_constituent_tendencies units = none type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension,1:number_of_ccpp_constituents) + dimensions = (horizontal_loop_extent,vertical_layer_dimension,number_of_ccpp_constituents) intent = out [ dpdry ] - standard_name = pressure_thickness_of_dry_air_for_deep_convection_for_convective_columns? + standard_name = air_pressure_thickness_of_dry_air units = hPa type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in +[ const_metadata ] + standard_name = ccpp_constituent_properties + units = None + type = ccpp_constituent_prop_ptr_t + dimensions = (number_of_ccpp_constituents) intent = in +[ scheme_name ] + standard_name = scheme_name + long_name = scheme name + units = none + type = character | kind = len=40 + dimensions = () + intent = out +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () + intent = out diff --git a/schemes/zhang_mcfarlane/zm_conv_evap.F90 b/schemes/zhang_mcfarlane/zm_conv_evap.F90 index dc87fe42..7f15f541 100644 --- a/schemes/zhang_mcfarlane/zm_conv_evap.F90 +++ b/schemes/zhang_mcfarlane/zm_conv_evap.F90 @@ -2,9 +2,6 @@ module zm_conv_evap use ccpp_kinds, only: kind_phys -! CACNOTE - Need to ccpp'ize cloud_fraction - use cloud_fraction, only: cldfrc_fice - implicit none save @@ -23,13 +20,12 @@ module zm_conv_evap !! subroutine zm_conv_evap_run(ncol, pver, pverp, & gravit, latice, latvap, tmelt, & - cpres, ke, ke_lnd, zm_org, & + cpres, ke, ke_lnd, & t,pmid,pdel,q, & landfrac, & tend_s, tend_s_snwprd, tend_s_snwevmlt, tend_q, & - prdprec, cldfrc, deltat, & - prec, snow, ntprprd, ntsnprd, flxprec, flxsnow, prdsnow) - + prdprec_gen, cldfrc, deltat, & + prec_gen, snow, ntprprd, ntsnprd, fsnow_conv, flxprec, flxsnow, scheme_name, errmsg, errflg) !----------------------------------------------------------------------- ! Compute tendencies due to evaporation of rain from ZM scheme @@ -40,7 +36,6 @@ subroutine zm_conv_evap_run(ncol, pver, pverp, & ! Evaporate some of the precip directly into the environment using a Sundqvist type algorithm !----------------------------------------------------------------------- -!CACNOTE - Not sure what to do about qsat_water use wv_saturation, only: qsat !------------------------------Arguments-------------------------------- @@ -53,39 +48,39 @@ subroutine zm_conv_evap_run(ncol, pver, pverp, & real(kind_phys), intent(in) :: cpres ! specific heat at constant pressure in j/kg-degk. real(kind_phys), intent(in) :: ke ! Tunable evaporation efficiency set from namelist input zmconv_ke real(kind_phys), intent(in) :: ke_lnd - logical, intent(in) :: zm_org real(kind_phys),intent(in), dimension(:,:) :: t ! temperature (K) (ncol,pver) real(kind_phys),intent(in), dimension(:,:) :: pmid ! midpoint pressure (Pa) (ncol,pver) real(kind_phys),intent(in), dimension(:,:) :: pdel ! layer thickness (Pa) (ncol,pver) real(kind_phys),intent(in), dimension(:,:) :: q ! water vapor (kg/kg) (ncol,pver) real(kind_phys),intent(in), dimension(:) :: landfrac ! land fraction (ncol) - real(kind_phys),intent(inout), dimension(:,:) :: tend_s ! heating rate (J/kg/s) (ncol,pver) - real(kind_phys),intent(inout), dimension(:,:) :: tend_q ! water vapor tendency (kg/kg/s) (ncol,pver) + + real(kind_phys),intent(out), dimension(:,:) :: tend_s ! heating rate (J/kg/s) (ncol,pver) + real(kind_phys),intent(out), dimension(:,:) :: tend_q ! water vapor tendency (kg/kg/s) (ncol,pver) real(kind_phys),intent(out), dimension(:,:) :: tend_s_snwprd ! Heating rate of snow production (ncol,pver) real(kind_phys),intent(out), dimension(:,:) :: tend_s_snwevmlt ! Heating rate of evap/melting of snow (ncol,pver) - - - real(kind_phys), intent(in ) :: prdprec(:,:)! precipitation production (kg/ks/s) (ncol,pver) + real(kind_phys), intent(in ) :: prdprec_gen(:,:)! precipitation production (kg/ks/s) (ncol,pver) real(kind_phys), intent(in ) :: cldfrc(:,:) ! cloud fraction (ncol,pver) real(kind_phys), intent(in ) :: deltat ! time step + real(kind_phys), intent(in ) :: fsnow_conv(:,:) ! snow fraction in precip production - real(kind_phys), intent(inout) :: prec(:) ! Convective-scale preciptn rate (ncol) + real(kind_phys), intent(inout) :: prec_gen(:) ! Convective-scale preciptn rate (ncol) real(kind_phys), intent(out) :: snow(:) ! Convective-scale snowfall rate (ncol) - real(kind_phys), optional, intent(in), allocatable :: prdsnow(:,:) ! snow production (kg/ks/s) - ! !---------------------------Local storage------------------------------- - real(kind_phys) :: es (ncol,pver) ! Saturation vapor pressure - real(kind_phys) :: fice (ncol,pver) ! ice fraction in precip production - real(kind_phys) :: fsnow_conv(ncol,pver) ! snow fraction in precip production + real(kind_phys) :: es (ncol,pver) ! Saturation vapor pressure real(kind_phys) :: qs (ncol,pver) ! saturation specific humidity real(kind_phys),intent(out) :: flxprec(:,:) ! Convective-scale flux of precip at interfaces (kg/m2/s) ! (ncol,pverp) real(kind_phys),intent(out) :: flxsnow(:,:) ! Convective-scale flux of snow at interfaces (kg/m2/s) ! (ncol,pverp) real(kind_phys),intent(out) :: ntprprd(:,:) ! net precip production in layer ! (ncol,pver) real(kind_phys),intent(out) :: ntsnprd(:,:) ! net snow production in layer ! (ncol,pver) + + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + character(len=40), intent(out) :: scheme_name + real(kind_phys) :: work1 ! temp variable (pjr) real(kind_phys) :: work2 ! temp variable (pjr) @@ -106,29 +101,19 @@ subroutine zm_conv_evap_run(ncol, pver, pverp, & !----------------------------------------------------------------------- + scheme_name = "zm_conv_evap_run" + errmsg = '' + errflg = 0 - ! If prdsnow is passed in and allocated, then use it in the calculation, otherwise - ! use the old snow calculation old_snow=.true. - if (present(prdsnow)) then - if (allocated(prdsnow)) then - old_snow=.false. - end if - end if ! convert input precip to kg/m2/s - prec(:ncol) = prec(:ncol)*1000._kind_phys + prec_gen(:ncol) = prec_gen(:ncol)*1000._kind_phys ! determine saturation vapor pressure do k = 1,pver call qsat(t(1:ncol,k), pmid(1:ncol,k), es(1:ncol,k), qs(1:ncol,k), ncol) end do -! determine ice fraction in rain production (use cloud water parameterization fraction at present) -!REMOVECAM - no longer need these when CAM is retired and pcols no longer exists - fice(:,:) = 0._kind_phys - fsnow_conv(:,:) = 0._kind_phys -!REMOVECAM_END - call cldfrc_fice(ncol, t(1:ncol,:), fice(1:ncol,:), fsnow_conv(1:ncol,:)) ! zero the flux integrals on the top boundary flxprec(:ncol,1) = 0._kind_phys @@ -140,7 +125,7 @@ subroutine zm_conv_evap_run(ncol, pver, pverp, & do i = 1, ncol ! Melt snow falling into layer, if necessary. - if( old_snow ) then + if( old_snow ) then if (t(i,k) > tmelt) then flxsntm(i) = 0._kind_phys snowmlt(i) = flxsnow(i,k) * gravit/ pdel(i,k) @@ -172,11 +157,7 @@ subroutine zm_conv_evap_run(ncol, pver, pverp, & ! relative humidity depression must be > 0 for evaporation evplimit = max(1._kind_phys - q(i,k)/qs(i,k), 0._kind_phys) - if (zm_org) then - kemask = ke * (1._kind_phys - landfrac(i)) + ke_lnd * landfrac(i) - else - kemask = ke - endif + kemask = ke ! total evaporation depends on flux in the top of the layer ! flux prec is the net production above layer minus evaporation into environmet @@ -192,7 +173,7 @@ subroutine zm_conv_evap_run(ncol, pver, pverp, & evplimit = min(evplimit, flxprec(i,k) * gravit / pdel(i,k)) ! Total evaporation cannot exceed input precipitation - evplimit = min(evplimit, (prec(i) - evpvint(i)) * gravit / pdel(i,k)) + evplimit = min(evplimit, (prec_gen(i) - evpvint(i)) * gravit / pdel(i,k)) evpprec(i) = min(evplimit, evpprec(i)) if( .not.old_snow ) then @@ -214,7 +195,7 @@ subroutine zm_conv_evap_run(ncol, pver, pverp, & evpvint(i) = evpvint(i) + evpprec(i) * pdel(i,k)/gravit ! net precip production is production - evaporation - ntprprd(i,k) = prdprec(i,k) - evpprec(i) + ntprprd(i,k) = prdprec_gen(i,k) - evpprec(i) ! net snow production is precip production * ice fraction - evaporation - melting ! the small amount added to flxprec in the work1 expression has been increased from ! 1e-36 to 8.64e-11 (1e-5 mm/day). This causes the temperature based partitioning @@ -229,13 +210,9 @@ subroutine zm_conv_evap_run(ncol, pver, pverp, & work2 = max(fsnow_conv(i,k), work1) if (snowmlt(i).gt.0._kind_phys) work2 = 0._kind_phys - ntsnprd(i,k) = prdprec(i,k)*work2 - evpsnow(i) - snowmlt(i) - tend_s_snwprd (i,k) = prdprec(i,k)*work2*latice + ntsnprd(i,k) = prdprec_gen(i,k)*work2 - evpsnow(i) - snowmlt(i) + tend_s_snwprd (i,k) = prdprec_gen(i,k)*work2*latice tend_s_snwevmlt(i,k) = - ( evpsnow(i) + snowmlt(i) )*latice - else - ntsnprd(i,k) = prdsnow(i,k) - min(flxsnow(i,k)*gravit/pdel(i,k), evpsnow(i)+snowmlt(i)) - tend_s_snwprd (i,k) = prdsnow(i,k)*latice - tend_s_snwevmlt(i,k) = -min(flxsnow(i,k)*gravit/pdel(i,k), evpsnow(i)+snowmlt(i) )*latice end if ! precipitation fluxes @@ -259,7 +236,7 @@ subroutine zm_conv_evap_run(ncol, pver, pverp, & end do ! set output precipitation rates (m/s) - prec(:ncol) = flxprec(:ncol,pver+1) / 1000._kind_phys + prec_gen(:ncol) = flxprec(:ncol,pver+1) / 1000._kind_phys snow(:ncol) = flxsnow(:ncol,pver+1) / 1000._kind_phys end subroutine zm_conv_evap_run diff --git a/schemes/zhang_mcfarlane/zm_conv_evap.meta b/schemes/zhang_mcfarlane/zm_conv_evap.meta index f352f803..42e9fd84 100644 --- a/schemes/zhang_mcfarlane/zm_conv_evap.meta +++ b/schemes/zhang_mcfarlane/zm_conv_evap.meta @@ -1,7 +1,7 @@ [ccpp-table-properties] name = zm_conv_evap type = scheme - + dependencies = ../../to_be_ccppized/wv_saturation.F90 [ccpp-arg-table] name = zm_conv_evap_run type = scheme @@ -30,112 +30,108 @@ dimensions = () intent = in [ latice ] - standard_name = latent_heat_of_fusion_of_water_at_0c? - units = J kg-1? + standard_name = latent_heat_of_fusion_of_water_at_0c + units = J kg-1 type = real | kind = kind_phys dimensions = () intent = in [ latvap ] - standard_name = latent_heat_of_vaporization_of_water_at_0c? - units = J kg-1? + standard_name = latent_heat_of_vaporization_of_water_at_0c + units = J kg-1 type = real | kind = kind_phys dimensions = () intent = in [ tmelt ] - standard_name = freezing_point_of_water? - units = K? + standard_name = freezing_point_of_water + units = K type = real | kind = kind_phys dimensions = () intent = in [ cpres ] - standard_name = specific_heat_of_dry_air_at_constant_pressure? - units = J kg-1 K-1? + standard_name = specific_heat_of_dry_air_at_constant_pressure + units = J kg-1 K-1 type = real | kind = kind_phys dimensions = () intent = in [ ke ] - standard_name = tunable_evaporation_efficiency_in_zhang_mcfarlane_deep_convection_scheme? - units = 1? + standard_name = tunable_evaporation_efficiency_over_ocean_for_zhang_mcfarlane_deep_convection_scheme + units = 1 type = real | kind = kind_phys dimensions = () intent = in [ ke_lnd ] - standard_name = tunable_evaporation_efficiency_for_land_in_zhang_mcfarlane_deep_convection_scheme? - units = 1? + standard_name = tunable_evaporation_efficiency_over_land_for_zhang_mcfarlane_deep_convection_scheme + units = 1 type = real | kind = kind_phys dimensions = () intent = in -[ zm_org ] - standard_name = flag_for_zhang_mcfarlane_convective_organization_parameterization? - units = flag? - type = logical - dimensions = () - intent = in [ t ] standard_name = air_temperature units = K type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ pmid ] standard_name = air_pressure units = Pa type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ pdel ] - standard_name = pressure_thickness + standard_name = air_pressure_thickness units = Pa type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ q ] standard_name = water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water units = kg kg-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in + advected = true [ landfrac ] standard_name = land_area_fraction - units = frac + units = fraction type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in [ tend_s ] - standard_name = heating_rate + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure units = J kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) - intent = inout + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = out [ tend_s_snwprd ] - standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_production_in_deep_convection? - units = tbd + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_production_due_to_convection + units = J kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ tend_s_snwevmlt ] - standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_frozen_precipitation_melt? - units = tbd + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure_due_to_evaporation_and_melting_of_frozen_precipitation_due_to_convection + units = J kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ tend_q ] - standard_name = tendency_of_water_vapor_mixing_ratio_wrt_moist_air and_condensed_water? - units = kg kg-1? + standard_name = tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water + units = kg kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) - intent = inout -[ prdprec ] - standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection_excluding_subcloud_evaporation + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = out + constituent = true +[ prdprec_gen ] + standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_convection_excluding_subcloud_evaporation units = kg kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ cldfrc ] standard_name = cloud_area_fraction - units = tbd + units = fraction type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ deltat ] standard_name = timestep_for_physics @@ -143,46 +139,66 @@ type = real | kind = kind_phys dimensions = () intent = in -[ prec ] - standard_name = lwe_precipitation_rate_at_surface_due_to_deep_convection +[ prec_gen ] + standard_name = lwe_precipitation_rate_at_surface_due_to_convection units = m s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = inout [ snow ] - standard_name = lwe_frozen_precipitation_rate_at_surface_due_to_deep_convection + standard_name = lwe_frozen_precipitation_rate_at_surface_due_to_convection units = m s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = out [ ntprprd ] - standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection? - units = kg kg-1 s-1? + standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_convection + units = kg kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ ntsnprd ] - standard_name = tendency_of_frozen_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection? - units = kg kg-1 s-1? + standard_name = tendency_of_frozen_precipitation_wrt_moist_air_and_condensed_water_due_to_convection + units = kg kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out +[ fsnow_conv ] + standard_name = mass_fraction_of_snow_content_within_stratiform_cloud + units = fraction + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = in [ flxprec ] - standard_name = precipitation_mass_flux_at_interface_due_to_deep_convection? - units = kg m-2 s-1? + standard_name = precipitation_flux_at_interface_due_to_convection + units = kg m-2 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_interface_dimension) intent = out [ flxsnow ] - standard_name = frozen_precipitation_mass_flux_at_interface_due_to_deep_convection? - units = kg m-2 s-1? + standard_name = frozen_precipitation_flux_at_interface_due_to_convection + units = kg m-2 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_interface_dimension) + intent = out +[ scheme_name ] + standard_name = scheme_name + long_name = scheme name + units = none + type = character | kind = len=40 + dimensions = () + intent = out +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () intent = out -[ prdsnow ] - standard_name = -tendency_of_frozen_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection_excluding_subcloud_evaporation? - units = kg kg-1 s-1? - type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) - intent = in diff --git a/schemes/zhang_mcfarlane/zm_conv_momtran.F90 b/schemes/zhang_mcfarlane/zm_conv_momtran.F90 index 0f9c07af..a4b43419 100644 --- a/schemes/zhang_mcfarlane/zm_conv_momtran.F90 +++ b/schemes/zhang_mcfarlane/zm_conv_momtran.F90 @@ -7,6 +7,7 @@ module zm_conv_momtran save private ! Make default type private to the module public zm_conv_momtran_run ! convective momentum transport + integer, parameter, private :: num_winds=2 ! Number of wind directions (for historical purposes) contains @@ -16,12 +17,12 @@ module zm_conv_momtran !! \htmlinclude zm_conv_momtran_run.html !! subroutine zm_conv_momtran_run(ncol, pver, pverp, & - domomtran,windu, windv,num_winds, mu, md, & + domomtran,windu, windv, mu, md, & momcu, momcd, & du, eu, ed, dp, dsubcld , & jt, mx, ideep , il1g, il2g, & nstep, windu_tend, windv_tend, pguallu, pguallv, pgdallu, pgdallv, & - icwuu, icwuv, icwdu, icwdv, dt, seten) + icwuu, icwuv, icwdu, icwdv, dt, seten, scheme_name, errmsg, errflg) !----------------------------------------------------------------------- ! ! Purpose: @@ -36,8 +37,6 @@ subroutine zm_conv_momtran_run(ncol, pver, pverp, & ! Author: J. Richter and P. Rasch ! !----------------------------------------------------------------------- -! CACNOTE - use CCPP constituents object - use constituents, only: cnst_get_type_byind implicit none !----------------------------------------------------------------------- @@ -45,9 +44,8 @@ subroutine zm_conv_momtran_run(ncol, pver, pverp, & ! Input arguments ! integer, intent(in) :: ncol ! number of atmospheric columns - integer, intent(in) :: num_winds ! number of wind directions integer, intent(in) :: pver, pverp - logical, intent(in) :: domomtran(:) ! flag for doing convective transport (num_winds) + logical, intent(in) :: domomtran ! flag for doing convective transport real(kind_phys), intent(in) :: windu(:,:) ! U Wind array (ncol,pver) real(kind_phys), intent(in) :: windv(:,:) ! V Wind array (ncol,pver) real(kind_phys), intent(in) :: mu(:,:) ! Mass flux up (ncol,pver) @@ -59,7 +57,7 @@ subroutine zm_conv_momtran_run(ncol, pver, pverp, & real(kind_phys), intent(in) :: ed(:,:) ! Mass entraining from downdraft (ncol,pver) real(kind_phys), intent(in) :: dp(:,:) ! Delta pressure between interfaces (ncol,pver) real(kind_phys), intent(in) :: dsubcld(:) ! Delta pressure from cloud base to sfc (ncol) - real(kind_phys), intent(in) :: dt ! time step in seconds + real(kind_phys), intent(in) :: dt ! time step in seconds integer, intent(in) :: jt(:) ! Index of cloud top for each column (ncol) integer, intent(in) :: mx(:) ! Index of cloud top for each column (ncol) @@ -75,6 +73,10 @@ subroutine zm_conv_momtran_run(ncol, pver, pverp, & real(kind_phys), intent(out) :: windu_tend(:,:) ! U wind tendency real(kind_phys), intent(out) :: windv_tend(:,:) ! V wind tendency + character(len=512), intent(out) :: errmsg + integer, intent(out) :: errflg + character(len=40), intent(out) :: scheme_name + !--------------------------Local Variables------------------------------ integer i ! Work index @@ -143,7 +145,10 @@ subroutine zm_conv_momtran_run(ncol, pver, pverp, & !----------------------------------------------------------------------- -! + scheme_name = "zm_conv_momtran_run" + errmsg = '' + errflg = 0 + ! Combine winds in single array winds(:,:,1) = windu(:,:) winds(:,:,2) = windv(:,:) @@ -178,7 +183,7 @@ subroutine zm_conv_momtran_run(ncol, pver, pverp, & ! Loop ever each wind component do m = 1, num_winds !start at m = 1 to transport momentum - if (domomtran(m)) then + if (domomtran) then ! Gather up the winds and set tend to zero do k = 1,pver diff --git a/schemes/zhang_mcfarlane/zm_conv_momtran.meta b/schemes/zhang_mcfarlane/zm_conv_momtran.meta index 82576cd8..4f289f9d 100644 --- a/schemes/zhang_mcfarlane/zm_conv_momtran.meta +++ b/schemes/zhang_mcfarlane/zm_conv_momtran.meta @@ -24,110 +24,104 @@ dimensions = () intent = in [ domomtran ] - standard_name = flag_for_zhang_mcfarlane_deep_momentum_transport? - units = flag? + standard_name = flag_for_momentum_transport_by_zhang_mcfarlane_deep_convection_scheme + units = flag type = logical - dimensions = (2) + dimensions = () intent = in [ windu ] - standard_name = enter_name - units = enter_name + standard_name = eastward_wind + units = m s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ windv ] - standard_name = enter_name - units = enter_name + standard_name = northward_wind + units = m s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) - intent = in -[ num_winds ] - standard_name = enter_name - units = enter_name - type = integer - dimensions = () + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ mu ] standard_name = atmosphere_updraft_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = hPa s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ md ] standard_name = atmosphere_downdraft_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = hPa s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ momcu ] - standard_name = momentum_upward_transport_parameter_for_zhang_mcfarlane? - units = tbd + standard_name = momentum_transport_parameter_for_vertical_pressure_gradient_force_for_updraft_for_zhang_mcfarlane_deep_convection_scheme + units = 1 type = real | kind = kind_phys dimensions = () intent = in [ momcd ] - standard_name = momentum_downward_transport_parameter_for_zhang_mcfarlane? - units = tbd + standard_name = momentum_transport_parameter_for_vertical_pressure_gradient_force_for_downdraft_for_zhang_mcfarlane_deep_convection_scheme + units = 1 type = real | kind = kind_phys dimensions = () intent = in [ du ] standard_name = atmosphere_detrainment_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ eu ] standard_name = atmosphere_updraft_entrainment_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ ed ] standard_name = atmosphere_downdraft_entrainment_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ dp ] standard_name = pressure_thickness_for_deep_convection_for_convective_columns units = hPa type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ dsubcld ] standard_name = pressure_thickness_for_subcloud_layer_for_deep_convection_for_convective_columns units = hPa type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in [ jt ] standard_name = vertical_index_at_top_of_deep_convection_for_convective_columns units = index type = integer - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in [ mx ] - standard_name = vertical_index_of_deep_conveciton_launch_level_for_convective_columns + standard_name = vertical_index_of_deep_convection_launch_level_for_convective_columns units = index type = integer - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in [ ideep ] standard_name = horizontal_index_of_convective_columns_for_deep_convection_for_convective_columns units = index type = integer - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in [ il1g ] - standard_name = minimum_number_of_grid_cells_with_deep_convection? - units = 1 + standard_name = index_of_first_column_of_gathered_deep_convection_arrays + units = index type = integer dimensions = () intent = in [ il2g ] - standard_name = maximum_number_of_grid_cells_with_deep_convection? - units = 1 + standard_name = index_of_last_column_of_gathered_deep_convection_arrays + units = index type = integer dimensions = () intent = in @@ -138,64 +132,64 @@ dimensions = () intent = in [ windu_tend ] - standard_name = enter_name - units = enter_name + standard_name = tendency_of_eastward_wind + units = m s-2 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ windv_tend ] - standard_name = enter_name - units = enter_name + standard_name = tendency_of_northward_wind + units = m s-2 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ pguallu ] standard_name = tendency_of_eastward_wind_due_to_zhang_mcfarlane_deep_convective_updraft_pressure_gradient_term - units = tbd + units = m s-2 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ pguallv ] standard_name = tendency_of_northward_wind_due_to_zhang_mcfarlane_deep_convective_updraft_pressure_gradient_term - units = tbd + units = m s-2 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ pgdallu ] standard_name = tendency_of_eastward_wind_due_to_zhang_mcfarlane_deep_convective_downdraft_pressure_gradient_term - units = tbd + units = m s-2 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ pgdallv ] standard_name = tendency_of_northward_wind_due_to_zhang_mcfarlane_deep_convective_downdraft_pressure_gradient_term - units = tbd + units = m s-2 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ icwuu ] - standard_name = eastward_wind - units = tbd + standard_name = in_cloud_eastward_wind_in_updraft_due_to_deep_convection + units = m s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ icwuv ] - standard_name = northward_wind - units = tbd + standard_name = in_cloud_northward_wind_in_updraft_due_to_deep_convection + units = m s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ icwdu ] - standard_name = eastward_and_northward_winds_in_deep_convective_downdrafts? - units = tbd + standard_name = in_cloud_eastward_wind_in_downdraft_due_to_deep_convection + units = m s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ icwdv ] - standard_name = eastward_and_northward_winds_in_deep_convective_downdrafts? - units = tbd + standard_name = in_cloud_northward_wind_in_downdraft_due_to_deep_convection + units = m s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ dt ] standard_name = timestep_for_physics @@ -207,5 +201,26 @@ standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure units = J kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = out +[ scheme_name ] + standard_name = scheme_name + long_name = scheme name + units = none + type = character | kind = len=40 + dimensions = () + intent = out +[ errmsg ] + standard_name = ccpp_error_message + long_name = Error message for error handling in CCPP + units = none + type = character | kind = len=512 + dimensions = () + intent = out +[ errflg ] + standard_name = ccpp_error_code + long_name = Error flag for error handling in CCPP + units = 1 + type = integer + dimensions = () intent = out diff --git a/schemes/zhang_mcfarlane/zm_convr.F90 b/schemes/zhang_mcfarlane/zm_convr.F90 index a938ace2..dbe80d1c 100644 --- a/schemes/zhang_mcfarlane/zm_convr.F90 +++ b/schemes/zhang_mcfarlane/zm_convr.F90 @@ -23,7 +23,6 @@ module zm_convr integer :: num_cin ! set from namelist input zmconv_num_cin ! The number of negative buoyancy regions that are allowed ! before the convection top and CAPE calculations are completed. - logical :: zm_org real(kind_phys) tau ! convective time scale real(kind_phys) :: tfreez real(kind_phys) :: eps1 @@ -55,20 +54,23 @@ module zm_convr !> \section arg_table_zm_convr_init Argument Table !! \htmlinclude zm_convr_init.html !! -subroutine zm_convr_init(cpair, epsilo, gravit, latvap, tmelt, rair, & - limcnv_in, zmconv_c0_lnd, zmconv_c0_ocn, zmconv_ke, zmconv_ke_lnd, & - zmconv_momcu, zmconv_momcd, zmconv_num_cin, zmconv_org, & +subroutine zm_convr_init(plev, plevp, cpair, epsilo, gravit, latvap, tmelt, rair, & + pref_edge, zmconv_c0_lnd, zmconv_c0_ocn, zmconv_ke, zmconv_ke_lnd, & + zmconv_momcu, zmconv_momcd, zmconv_num_cin, & no_deep_pbl_in, zmconv_tiedke_add, & zmconv_capelmt, zmconv_dmpdz, zmconv_parcel_pbl, zmconv_tau, & masterproc, iulog, errmsg, errflg) + integer, intent(in) :: plev + integer, intent(in) :: plevp + real(kind_phys), intent(in) :: cpair ! specific heat of dry air (J K-1 kg-1) real(kind_phys), intent(in) :: epsilo ! ratio of h2o to dry air molecular weights real(kind_phys), intent(in) :: gravit ! gravitational acceleration (m s-2) real(kind_phys), intent(in) :: latvap ! Latent heat of vaporization (J kg-1) real(kind_phys), intent(in) :: tmelt ! Freezing point of water (K) real(kind_phys), intent(in) :: rair ! Dry air gas constant (J K-1 kg-1) - integer, intent(in) :: limcnv_in ! top interface level limit for convection + real(kind_phys), intent(in) :: pref_edge(:) ! reference pressures at interfaces integer, intent(in) :: zmconv_num_cin ! Number negative buoyancy regions that are allowed ! before the convection top and CAPE calculations are completed. real(kind_phys),intent(in) :: zmconv_c0_lnd @@ -77,7 +79,6 @@ subroutine zm_convr_init(cpair, epsilo, gravit, latvap, tmelt, rair, & real(kind_phys),intent(in) :: zmconv_ke_lnd real(kind_phys),intent(in) :: zmconv_momcu real(kind_phys),intent(in) :: zmconv_momcd - logical, intent(in) :: zmconv_org logical, intent(in) :: no_deep_pbl_in ! no_deep_pbl = .true. eliminates ZM convection entirely within PBL real(kind_phys),intent(in) :: zmconv_tiedke_add real(kind_phys),intent(in) :: zmconv_capelmt @@ -89,11 +90,12 @@ subroutine zm_convr_init(cpair, epsilo, gravit, latvap, tmelt, rair, & character(len=512), intent(out) :: errmsg integer, intent(out) :: errflg + integer :: k + errmsg ='' errflg = 0 ! Initialization of ZM constants - limcnv = limcnv_in tfreez = tmelt eps1 = epsilo rl = latvap @@ -108,7 +110,6 @@ subroutine zm_convr_init(cpair, epsilo, gravit, latvap, tmelt, rair, & num_cin = zmconv_num_cin ke = zmconv_ke ke_lnd = zmconv_ke_lnd - zm_org = zmconv_org momcu = zmconv_momcu momcd = zmconv_momcd @@ -120,7 +121,26 @@ subroutine zm_convr_init(cpair, epsilo, gravit, latvap, tmelt, rair, & tau = zmconv_tau - if ( masterproc ) then + ! + ! Limit deep convection to regions below 40 mb + ! Note this calculation is repeated in the shallow convection interface + ! + limcnv = 0 ! null value to check against below + if (pref_edge(1) >= 4.e3_kind_phys) then + limcnv = 1 + else + do k=1,plev + if (pref_edge(k) < 4.e3_kind_phys .and. pref_edge(k+1) >= 4.e3_kind_phys) then + limcnv = k + exit + end if + end do + if ( limcnv == 0 ) limcnv = plevp + end if + + if ( masterproc ) then + write(iulog,*)'ZM_CONV_INIT: Deep convection will be capped at intfc ',limcnv, & + ' which is ',pref_edge(limcnv),' pascals' write(iulog,*) 'tuning parameters zm_convr_init: tau',tau write(iulog,*) 'tuning parameters zm_convr_init: c0_lnd',c0_lnd, ', c0_ocn', c0_ocn write(iulog,*) 'tuning parameters zm_convr_init: num_cin', num_cin @@ -143,17 +163,16 @@ end subroutine zm_convr_init !! subroutine zm_convr_run( ncol ,pver , & pverp, gravit ,latice ,cpwv ,cpliq , rh2o, & + lat, long, & t ,qh ,prec , & pblh ,zm ,geos ,zi ,qtnd , & heat ,pap ,paph ,dpp , & delt ,mcon ,cme ,cape , & - tpert ,dlf ,zdu ,rprd , & + tpert ,dlf ,dif ,zdu ,rprd , & mu ,md ,du ,eu ,ed , & dp ,dsubcld ,jt ,maxg ,ideep , & ql ,rliq ,landfrac, & - org ,orgt ,org2d , & - dif ,dnlf ,dnif , & - rice ,errmsg ,errflg) + rice ,lengath ,scheme_name, errmsg ,errflg) !----------------------------------------------------------------------- ! ! Purpose: @@ -276,6 +295,9 @@ subroutine zm_convr_run( ncol ,pver , & real(kind_phys), intent(in) :: cpliq ! specific heat of fresh h2o (J K-1 kg-1) real(kind_phys), intent(in) :: rh2o ! Water vapor gas constant (J K-1 kg-1) + real(kind_phys), intent(in) :: lat(:) + real(kind_phys), intent(in) :: long(:) + real(kind_phys), intent(in) :: t(:,:) ! grid slice of temperature at mid-layer. (ncol,pver) real(kind_phys), intent(in) :: qh(:,:) ! grid slice of specific humidity. (ncol,pver) real(kind_phys), intent(in) :: pap(:,:) ! (ncol,pver) @@ -293,14 +315,12 @@ subroutine zm_convr_run( ncol ,pver , & real(kind_phys), intent(out) :: qtnd(:,:) ! specific humidity tendency (kg/kg/s) (ncol,pver) real(kind_phys), intent(out) :: heat(:,:) ! heating rate (dry static energy tendency, W/kg) (ncol,pver) real(kind_phys), intent(out) :: mcon(:,:) ! (ncol,pverp) + real(kind_phys), intent(out) :: dif(:,:) real(kind_phys), intent(out) :: dlf(:,:) ! scattrd version of the detraining cld h2o tend (ncol,pver) real(kind_phys), intent(out) :: cme(:,:) ! (ncol,pver) real(kind_phys), intent(out) :: cape(:) ! w convective available potential energy. (ncol) real(kind_phys), intent(out) :: zdu(:,:) ! (ncol,pver) real(kind_phys), intent(out) :: rprd(:,:) ! rain production rate (ncol,pver) - real(kind_phys), intent(out) :: dif(:,:) ! detrained convective cloud ice mixing ratio. (ncol,pver) - real(kind_phys), intent(out) :: dnlf(:,:) ! detrained convective cloud water num concen. (ncol,pver) - real(kind_phys), intent(out) :: dnif(:,:) ! detrained convective cloud ice num concen. (ncol,pver) ! move these vars from local storage to output so that convective ! transports can be done in outside of conv_cam. @@ -317,35 +337,30 @@ subroutine zm_convr_run( ncol ,pver , & integer, intent(out) :: ideep(:) ! column indices of gathered points (ncol) + integer, intent(out) :: jt(:) ! wg top level index of deep cumulus convection. + integer, intent(out) :: maxg(:)! wg gathered values of maxi. + + integer, intent(out) :: lengath + + real(kind_phys),intent(out):: ql(:,:) ! wg grid slice of cloud liquid water. + + character(len=40), intent(out) :: scheme_name character(len=512), intent(out) :: errmsg integer, intent(out) :: errflg - real(kind_phys), intent(in) :: org(:,:) ! Only used if zm_org is true ! in - real(kind_phys), intent(out) :: orgt(:,:) ! Only used if zm_org is true ! out - real(kind_phys), intent(out) :: org2d(:,:) ! Only used if zm_org is true ! out - ! Local variables + real(kind_phys) zs(ncol) real(kind_phys) dlg(ncol,pver) ! gathrd version of the detraining cld h2o tend real(kind_phys) cug(ncol,pver) ! gathered condensation rate real(kind_phys) evpg(ncol,pver) ! gathered evap rate of rain in downdraft - real(kind_phys) orgavg(ncol) real(kind_phys) dptot(ncol) real(kind_phys) mumax(ncol) -!CACNOTE - Figure out real intent for jt and maxg - integer, intent(inout) :: jt(ncol) ! wg top level index of deep cumulus convection. - integer, intent(inout) :: maxg(ncol) ! wg gathered values of maxi. - - integer lengath -! diagnostic field used by chem/wetdep codes - -!CACNOTE - Figure out real intent for ql - real(kind_phys),intent(inout):: ql(ncol,pver) ! wg grid slice of cloud liquid water. ! real(kind_phys) pblt(ncol) ! i row of pbl top indices. @@ -441,6 +456,7 @@ subroutine zm_convr_run( ncol ,pver , & ! !--------------------------Data statements------------------------------ + scheme_name = "zm_convr_run" errmsg = '' errflg = 0 ! @@ -452,9 +468,6 @@ subroutine zm_convr_run( ncol ,pver , & ! zero out variables not used in cam ! - if (zm_org) then - orgt(:,:) = 0._kind_phys - end if qtnd(:,:) = 0._kind_phys heat(:,:) = 0._kind_phys @@ -482,8 +495,6 @@ subroutine zm_convr_run( ncol ,pver , & qldeg(i,k) = 0._kind_phys dif(i,k) = 0._kind_phys - dnlf(i,k) = 0._kind_phys - dnif(i,k) = 0._kind_phys end do end do @@ -494,33 +505,6 @@ subroutine zm_convr_run( ncol ,pver , & end do - if (zm_org) then -! compute vertical average here - orgavg(:) = 0._kind_phys - dptot(:) = 0._kind_phys - - do k = 1, pver - do i = 1,ncol - if (org(i,k) .gt. 0) then - orgavg(i) = orgavg(i)+dpp(i,k)*org(i,k) - dptot(i) = dptot(i)+dpp(i,k) - endif - enddo - enddo - - do i = 1,ncol - if (dptot(i) .gt. 0) then - orgavg(i) = orgavg(i)/dptot(i) - endif - enddo - - do k = 1, pver - do i = 1, ncol - org2d(i,k) = orgavg(i) - enddo - enddo - - endif ! ! calculate local pressure (mbs) and height (m) for both interface @@ -579,8 +563,8 @@ subroutine zm_convr_run( ncol ,pver , & tp ,qstp ,tl ,rl ,cape , & pblt ,lcl ,lel ,lon ,maxi , & rgas ,grav ,cpres ,msg , & - zi ,zs ,tpert , org2d , landfrac,& - errmsg ,errflg) + zi ,zs ,tpert , landfrac,& + lat ,long ,errmsg ,errflg) ! ! determine whether grid points will undergo some deep convection @@ -819,8 +803,8 @@ subroutine buoyan_dilute( ncol ,pver , & tp ,qstp ,tl ,rl ,cape , & pblt ,lcl ,lel ,lon ,mx , & rd ,grav ,cp ,msg , & - zi ,zs ,tpert ,org , landfrac,& - errmsg ,errflg) + zi ,zs ,tpert , landfrac,& + lat ,long ,errmsg ,errflg) !----------------------------------------------------------------------- ! ! Purpose: @@ -870,6 +854,9 @@ subroutine buoyan_dilute( ncol ,pver , & real(kind_phys), intent(in) :: zi(ncol,pver+1) real(kind_phys), intent(in) :: zs(ncol) + real(kind_phys), intent(in) :: lat(:) + real(kind_phys), intent(in) :: long(:) + ! ! output arguments ! @@ -883,7 +870,6 @@ subroutine buoyan_dilute( ncol ,pver , & integer lon(ncol) ! level of onset of deep convection integer mx(ncol) ! level of max moist static energy - real(kind_phys) :: org(:,:) ! organization parameter real(kind_phys), intent(in) :: landfrac(ncol) character(len=512), intent(out) :: errmsg integer, intent(out) :: errflg @@ -1094,7 +1080,7 @@ subroutine buoyan_dilute( ncol ,pver , & call parcel_dilute(ncol, pver, cpliq, cpwv, rh2o, latice, msg, mx, p, t, q, & tpert, tp, tpv, qstp, pl, tl, ql, lcl, & - org, landfrac, errmsg, errflg) + landfrac, lat, long, errmsg, errflg) ! If lcl is above the nominal level of non-divergence (600 mbs), @@ -1177,7 +1163,7 @@ end subroutine buoyan_dilute subroutine parcel_dilute (ncol, pver, cpliq, cpwv, rh2o, latice, msg, klaunch, p, t, q, & tpert, tp, tpv, qstp, pl, tl, ql, lcl, & - org, landfrac,errmsg,errflg) + landfrac,lat,long,errmsg,errflg) ! Routine to determine ! 1. Tp - Parcel temperature @@ -1202,6 +1188,9 @@ subroutine parcel_dilute (ncol, pver, cpliq, cpwv, rh2o, latice, msg, klaunch, p real(kind_phys), intent(in), dimension(ncol,pver) :: q real(kind_phys), intent(in), dimension(ncol) :: tpert ! PBL temperature perturbation. +real(kind_phys), intent(in) :: lat(:) +real(kind_phys), intent(in) :: long(:) + real(kind_phys), intent(inout), dimension(ncol,pver) :: tp ! Parcel temp. real(kind_phys), intent(inout), dimension(ncol,pver) :: qstp ! Parcel water vapour (sat value above lcl). real(kind_phys), intent(inout), dimension(ncol) :: tl ! Actual temp of LCL. @@ -1217,7 +1206,6 @@ subroutine parcel_dilute (ncol, pver, cpliq, cpwv, rh2o, latice, msg, klaunch, p -real(kind_phys), dimension(:,:) :: org real(kind_phys), intent(in), dimension(ncol) :: landfrac !-------------------- @@ -1262,7 +1250,6 @@ subroutine parcel_dilute (ncol, pver, cpliq, cpwv, rh2o, latice, msg, klaunch, p real(kind_phys) qxsk, qxskp1 ! LCL excess water (k, k+1) real(kind_phys) dsdp, dqtdp, dqxsdp ! LCL s, qt, p gradients (k, k+1) real(kind_phys) slcl,qtlcl,qslcl ! LCL s, qt, qs values. -real(kind_phys) org2rkm, org2Tpert real(kind_phys) dmpdz_lnd, dmpdz_mask integer rcall ! Number of ientropy call for errors recording @@ -1282,10 +1269,6 @@ subroutine parcel_dilute (ncol, pver, cpliq, cpwv, rh2o, latice, msg, klaunch, p ! Set some values that may be changed frequently. ! -if (zm_org) then - org2rkm = 10._kind_phys - org2Tpert = 0._kind_phys -endif nit_lheat = 2 ! iterations for ds,dq changes from condensation freezing. dmpdz=dmpdz_param ! Entrainment rate. (-ve for /m) dmpdz_lnd=-1.e-3_kind_phys @@ -1337,7 +1320,8 @@ subroutine parcel_dilute (ncol, pver, cpliq, cpwv, rh2o, latice, msg, klaunch, p qtmix(i,k) = qtp0(i) tfguess = t(i,k) rcall = 1 - call ientropy (rcall,i,smix(i,k),p(i,k),qtmix(i,k),tmix(i,k),qsmix(i,k),tfguess,cpliq,cpwv,rh2o,errmsg,errflg) + call ientropy (rcall,i,smix(i,k),p(i,k),qtmix(i,k),tmix(i,k),qsmix(i,k),tfguess,cpliq,cpwv,rh2o,& + lat(i), long(i), errmsg,errflg) end if ! Entraining levels @@ -1357,12 +1341,7 @@ subroutine parcel_dilute (ncol, pver, cpliq, cpwv, rh2o, latice, msg, klaunch, p dpdz = -(penv*grav)/(rgas*tenv) ! in mb/m since p in mb. dzdp = 1._kind_phys/dpdz ! in m/mb - if (zm_org) then - dmpdz_mask = landfrac(i) * dmpdz_lnd + (1._kind_phys - landfrac(i)) * dmpdz - dmpdp = (dmpdz_mask/(1._kind_phys+org(i,k)*org2rkm))*dzdp ! /mb Fractional entrainment - else - dmpdp = dmpdz*dzdp - endif + dmpdp = dmpdz*dzdp ! Sum entrainment to current level ! entrains q,s out of intervening dp layers, in which linear variation is assumed @@ -1382,7 +1361,8 @@ subroutine parcel_dilute (ncol, pver, cpliq, cpwv, rh2o, latice, msg, klaunch, p tfguess = tmix(i,k+1) rcall = 2 - call ientropy(rcall,i,smix(i,k),p(i,k),qtmix(i,k),tmix(i,k),qsmix(i,k),tfguess,cpliq,cpwv,rh2o,errmsg,errflg) + call ientropy(rcall,i,smix(i,k),p(i,k),qtmix(i,k),tmix(i,k),qsmix(i,k),tfguess,cpliq,cpwv,rh2o,lat(i),& + long(i),errmsg,errflg) ! ! Determine if this is lcl of this column if qsmix <= qtmix. @@ -1401,7 +1381,7 @@ subroutine parcel_dilute (ncol, pver, cpliq, cpwv, rh2o, latice, msg, klaunch, p tfguess = tmix(i,k) rcall = 3 - call ientropy (rcall,i,slcl,pl(i),qtlcl,tl(i),qslcl,tfguess,cpliq,cpwv,rh2o,errmsg,errflg) + call ientropy (rcall,i,slcl,pl(i),qtlcl,tl(i),qslcl,tfguess,cpliq,cpwv,rh2o,lat(i), long(i), errmsg,errflg) ! write(iulog,*)' ' ! write(iulog,*)' p',p(i,k+1),pl(i),p(i,lcl(i)) @@ -1454,11 +1434,7 @@ subroutine parcel_dilute (ncol, pver, cpliq, cpwv, rh2o, latice, msg, klaunch, p tp(i,k) = tmix(i,k) qstp(i,k) = q(i,k) - if (zm_org) then - tpv(i,k) = (tp(i,k) + (org2Tpert*org(i,k)+tpert(i))) * (1._kind_phys+1.608_kind_phys*qstp(i,k)) / (1._kind_phys+qstp(i,k)) - else - tpv(i,k) = (tp(i,k) + tpert(i)) * (1._kind_phys+1.608_kind_phys*qstp(i,k)) / (1._kind_phys+qstp(i,k)) - endif + tpv(i,k) = (tp(i,k) + tpert(i)) * (1._kind_phys+1.608_kind_phys*qstp(i,k)) / (1._kind_phys+qstp(i,k)) end if @@ -1501,7 +1477,8 @@ subroutine parcel_dilute (ncol, pver, cpliq, cpwv, rh2o, latice, msg, klaunch, p tfguess = tmix(i,k) rcall =4 - call ientropy (rcall,i,new_s, p(i,k), new_q, tmix(i,k), qsmix(i,k), tfguess,cpliq,cpwv,rh2o,errmsg,errflg) + call ientropy (rcall,i,new_s, p(i,k), new_q, tmix(i,k), qsmix(i,k), tfguess,cpliq,cpwv,rh2o,& + lat(i), long(i), errmsg,errflg) end do ! Iteration loop for freezing processes. @@ -1518,11 +1495,7 @@ subroutine parcel_dilute (ncol, pver, cpliq, cpwv, rh2o, latice, msg, klaunch, p qstp(i,k) = new_q end if - if (zm_org) then - tpv(i,k) = (tp(i,k)+(org2Tpert*org(i,k)+tpert(i)))* (1._kind_phys+1.608_kind_phys*qstp(i,k)) / (1._kind_phys+ new_q) - else - tpv(i,k) = (tp(i,k)+tpert(i))* (1._kind_phys+1.608_kind_phys*qstp(i,k)) / (1._kind_phys+ new_q) - endif + tpv(i,k) = (tp(i,k)+tpert(i))* (1._kind_phys+1.608_kind_phys*qstp(i,k)) / (1._kind_phys+ new_q) end if ! k < klaunch @@ -1563,7 +1536,7 @@ end FUNCTION entropy ! !----------------------------------------------------------------------------------------- -SUBROUTINE ientropy (rcall,icol,s,p,qt,T,qst,Tfg,cpliq,cpwv,rh2o,errmsg,errflg) +SUBROUTINE ientropy (rcall,icol,s,p,qt,T,qst,Tfg,cpliq,cpwv,rh2o,this_lat,this_lon,errmsg,errflg) !----------------------------------------------------------------------------------------- ! ! p(mb), Tfg/T(K), qt/qv(kg/kg), s(J/kg). @@ -1571,19 +1544,20 @@ SUBROUTINE ientropy (rcall,icol,s,p,qt,T,qst,Tfg,cpliq,cpwv,rh2o,errmsg,errflg) ! for T and saturated vapor mixing ratio ! -! CACNOTE - Remove this when pass in lat/lon or pass out lchnk,icol (Note: lchnk will not exist in CAM-SIMA) -! use phys_grid, only: get_rlon_p, get_rlat_p - integer, intent(in) :: icol, rcall real(kind_phys), intent(in) :: s, p, Tfg, qt real(kind_phys), intent(in) :: cpliq real(kind_phys), intent(in) :: cpwv real(kind_phys), intent(in) :: rh2o + + real(kind_phys), intent(in) :: this_lat + real(kind_phys), intent(in) :: this_lon + real(kind_phys), intent(out) :: qst, T character(len=512), intent(out) :: errmsg integer, intent(out) :: errflg - real(kind_phys) :: est, this_lat,this_lon + real(kind_phys) :: est real(kind_phys) :: a,b,c,d,ebr,fa,fb,fc,pbr,qbr,rbr,sbr,tol1,xm,tol integer :: i @@ -1668,17 +1642,14 @@ SUBROUTINE ientropy (rcall,icol,s,p,qt,T,qst,Tfg,cpliq,cpwv,rh2o,errmsg,errflg) call qsat_hPa(T, p, est, qst) if (.not. converged) then -!CACNOTE - Revisit this with Jesse -! this_lat = get_rlat_p(lchnk, icol)*57.296_kind_phys -! this_lon = get_rlon_p(lchnk, icol)*57.296_kind_phys -! write(errmsg,100) 'ZM_CONV: IENTROPY. Details: call#,lchnk,icol= ',rcall,lchnk,icol, & -! ' lat: ',this_lat,' lon: ',this_lon, & -! ' P(mb)= ', p, ' Tfg(K)= ', Tfg, ' qt(g/kg) = ', 1000._kind_phys*qt, & -! ' qst(g/kg) = ', 1000._kind_phys*qst,', s(J/kg) = ',s + write(errmsg,100) ' ZM_CONV: IENTROPY. Details: call#,icol= ',rcall,icol, & + ' lat: ',this_lat,' lon: ',this_lon, & + ' P(mb)= ', p, ' Tfg(K)= ', Tfg, ' qt(g/kg) = ', 1000._kind_phys*qt, & + ' qst(g/kg) = ', 1000._kind_phys*qst,', s(J/kg) = ',s errflg=1 end if -100 format (A,I1,I4,I4,7(A,F6.2)) +100 format (A,I4,I4,7(A,F6.2)) end SUBROUTINE ientropy @@ -1694,28 +1665,9 @@ subroutine cldprp(ncol ,pver ,pverp ,cpliq , & rd ,grav ,cp ,msg , & evp ,cu ,rprd ,limcnv ,landfrac, & qcde ,qhat ) - -!----------------------------------------------------------------------- -!CACNOTE - fill in documentation -! -! Purpose: -! -! -! Method: -! may 09/91 - guang jun zhang, m.lazare, n.mcfarlane. -! original version cldprop. -! -! Author: See above, modified by P. Rasch -! This is contributed code not fully standardized by the CCM core group. -! -! this code is very much rougher than virtually anything else in the CCM -! there are debug statements left strewn about and code segments disabled -! these are to facilitate future development. We expect to release a -! cleaner code in a future release -! -! the documentation has been enhanced to the degree that we are able -! -!----------------------------------------------------------------------- +!---------------------------------------------- +! Purpose: Provide cloud properties +!---------------------------------------------- implicit none @@ -1829,7 +1781,6 @@ subroutine cldprp(ncol ,pver ,pverp ,cpliq , & real(kind_phys) small real(kind_phys) mdt - real(kind_phys) fice(ncol,pver) ! ice fraction in precip production real(kind_phys) tug(ncol,pver) real(kind_phys) tvuo(ncol,pver) ! updraft virtual T w/o freezing heating @@ -1907,7 +1858,6 @@ subroutine cldprp(ncol ,pver ,pverp ,cpliq , & hd(i,k) = hmn(i,k) rprd(i,k) = 0._kind_phys - fice(i,k) = 0._kind_phys tug(i,k) = 0._kind_phys qcde(i,k) = 0._kind_phys tvuo(i,k) = (shat(i,k) - grav/cp*zf(i,k))*(1._kind_phys + 0.608_kind_phys*qhat(i,k)) @@ -2405,26 +2355,6 @@ subroutine closure(ncol ,pver, & lcl ,lel ,jt ,mx ,il1g , & il2g ,rd ,grav ,cp ,rl , & msg ,capelmt ) -!----------------------------------------------------------------------- -!CACNOTE - fill in documentation -! -! Purpose: -! -! -! Method: -! -! -! -! Author: G. Zhang and collaborators. CCM contact:P. Rasch -! This is contributed code not fully standardized by the CCM core group. -! -! this code is very much rougher than virtually anything else in the CCM -! We expect to release cleaner code in a future release -! -! the documentation has been enhanced to the degree that we are able -! -!----------------------------------------------------------------------- - ! !-----------------------------Arguments--------------------------------- ! @@ -2617,17 +2547,8 @@ subroutine q1q2_pjr(ncol ,pver ,latice ,& implicit none !----------------------------------------------------------------------- -! CACNOTE -fill in documentation -! ! Purpose: -! -! -! Method: -! -! -! -! Author: phil rasch dec 19 1995 -! +! compute temperature and moisture changes due to convection. !----------------------------------------------------------------------- @@ -2742,7 +2663,6 @@ end subroutine q1q2_pjr ! qsat_water uses Pa internally, so get it right, need to pass in Pa. ! Afterward, set es back to hPa. subroutine qsat_hPa(t, p, es, qm) -!CACNOTE - Need to figure out how to handle this use wv_saturation, only: qsat_water ! Inputs diff --git a/schemes/zhang_mcfarlane/zm_convr.meta b/schemes/zhang_mcfarlane/zm_convr.meta index b1c76171..13c1ebee 100644 --- a/schemes/zhang_mcfarlane/zm_convr.meta +++ b/schemes/zhang_mcfarlane/zm_convr.meta @@ -1,19 +1,32 @@ [ccpp-table-properties] name = zm_convr type = scheme + dependencies = ../../to_be_ccppized/wv_saturation.F90 [ccpp-arg-table] name = zm_convr_init type = scheme +[ plev ] + standard_name = vertical_layer_dimension + units = count + type = integer + dimensions = () + intent = in +[ plevp ] + standard_name = vertical_interface_dimension + units = count + type = integer + dimensions = () + intent = in [ cpair ] - standard_name = composition_dependent_specific_heat_of_dry_air_at_constant_pressure + standard_name = specific_heat_of_dry_air_at_constant_pressure units = J kg-1 K-1 type = real | kind = kind_phys dimensions = () intent = in [ epsilo ] - standard_name = ratio_of_h2o_to_dry_air_molecular_weights? - units = 1? + standard_name = ratio_of_water_vapor_to_dry_air_molecular_weights + units = 1 type = real | kind = kind_phys dimensions = () intent = in @@ -24,122 +37,116 @@ dimensions = () intent = in [ latvap ] - standard_name = latent_heat_of_vaporization_of_water_at_0c? - units = J kg-1? + standard_name = latent_heat_of_vaporization_of_water_at_0c + units = J kg-1 type = real | kind = kind_phys dimensions = () intent = in [ tmelt ] - standard_name = freezing_point_of_water? - units = K? + standard_name = freezing_point_of_water + units = K type = real | kind = kind_phys dimensions = () intent = in [ rair ] - standard_name = composition_dependent_gas_constant_of_dry_air + standard_name = gas_constant_of_dry_air units = J kg-1 K-1 type = real | kind = kind_phys dimensions = () intent = in -[ limcnv_in ] - standard_name = vertical_interface_index_of_deep_convection_height_limit? - units = index? - type = integer - dimensions = () +[ pref_edge ] + standard_name = reference_pressure_at_interface + units = Pa + type = real | kind = kind_phys + dimensions = (vertical_interface_dimension) intent = in [ zmconv_c0_lnd ] - standard_name = condensate_to_precipitation_autoconversion_coefficient_over_land_for_zhang_mcfarlane? - units = 1? + standard_name = cloud_condensate_to_precipitation_autoconversion_coefficient_over_land_for_zhang_mcfarlane_deep_convection_scheme + units = m-1 type = real | kind = kind_phys dimensions = () intent = in [ zmconv_c0_ocn ] - standard_name = condensate_to_precipitation_autoconversion_coefficient_over_ocean_for_zhang_mcfarlane? - units = 1? + standard_name = cloud_condensate_to_precipitation_autoconversion_coefficient_over_ocean_for_zhang_mcfarlane_deep_convection_scheme + units = m-1 type = real | kind = kind_phys dimensions = () intent = in [ zmconv_ke ] - standard_name = tunable_evaporation_efficiency_in_zhang_mcfarlane_deep_convection_scheme? - units = 1? + standard_name = tunable_evaporation_efficiency_over_ocean_for_zhang_mcfarlane_deep_convection_scheme + units = 1 type = real | kind = kind_phys dimensions = () intent = in [ zmconv_ke_lnd ] - standard_name = tunable_evaporation_efficiency_for_land_in zhang_mcfarlane_deep_convection_scheme? - units = 1? + standard_name = tunable_evaporation_efficiency_over_land_for_zhang_mcfarlane_deep_convection_scheme + units = 1 type = real | kind = kind_phys dimensions = () intent = in [ zmconv_momcu ] - standard_name = momentum_upward_transport_parameter_for_zhang_mcfarlane? - units = 1? + standard_name = momentum_transport_parameter_for_vertical_pressure_gradient_force_for_updraft_for_zhang_mcfarlane_deep_convection_scheme + units = 1 type = real | kind = kind_phys dimensions = () intent = in [ zmconv_momcd ] - standard_name = momentum_downward_transport_parameter_for_zhang_mcfarlane? - units = tbd + standard_name = momentum_transport_parameter_for_vertical_pressure_gradient_force_for_downdraft_for_zhang_mcfarlane_deep_convection_scheme + units = 1 type = real | kind = kind_phys dimensions = () intent = in [ zmconv_num_cin ] - standard_name = number_of_negative_buoyancy_regions_allowed_before_convection_top_for_zhang_mcfarlane? - units = count? + standard_name = number_of_negative_buoyancy_layers_allowed_before_convection_top_for_zhang_mcfarlane_deep_convection_scheme + units = count type = integer dimensions = () intent = in -[ zmconv_org ] - standard_name = deep_convective_organization_amount_for_zhang_mcfarlane? - units = 1? - type = logical - dimensions = () - intent = in [ no_deep_pbl_in ] - standard_name = flag_for_no_deep_convection_in_pbl? - units = flag? + standard_name = flag_for_no_deep_convection_in_pbl + units = flag type = logical dimensions = () intent = in [ zmconv_tiedke_add ] - standard_name = parcel_temperature_perturbation_for_zhang_mcfarlane? - units = K? + standard_name = parcel_temperature_perturbation_for_zhang_mcfarlane_deep_convection_scheme + units = flag type = real | kind = kind_phys dimensions = () intent = in [ zmconv_capelmt ] - standard_name = deep_convection_triggering_cape_threshold_for_zhang_mcfarlane? - units = J kg-1? + standard_name = cape_threshold_for_zhang_mcfarlane_deep_convection_scheme + units = J kg-1 type = real | kind = kind_phys dimensions = () intent = in [ zmconv_dmpdz ] - standard_name = deep_convective_entrainment_rate_for_zhang_mcfarlane? - units = m-1? + standard_name = entrainment_rate_for_cape_for_zhang_mcfarlane_deep_convection_scheme + units = m-1 type = real | kind = kind_phys dimensions = () intent = in [ zmconv_parcel_pbl ] - standard_name = initial_parcel_property_as_function_of_well-mixed_pbl_for_zhang_mcfarlane? - units = flag? + standard_name = flag_for_well_mixed_pbl_parcel_property_for_zhang_mcfarlane_deep_convection_scheme + units = flag type = logical dimensions = () intent = in [ zmconv_tau ] - standard_name = deep_convective_adjustment_timescale_for_zhang_mcfarlane? - units = s? + standard_name = deep_convective_adjustment_timescale_for_zhang_mcfarlane_deep_convection_scheme + units = s type = real | kind = kind_phys dimensions = () intent = in [ masterproc ] - standard_name = enter_name - units = enter_name + standard_name = flag_for_mpi_root + units = flag type = logical dimensions = () intent = in [ iulog ] - standard_name = enter_name - units = enter_name + standard_name = log_output_unit + units = 1 type = integer dimensions = () intent = in @@ -186,100 +193,115 @@ dimensions = () intent = in [ latice ] - standard_name = latent_heat_of_fusion_of_water_at_0c? - units = J kg-1? + standard_name = latent_heat_of_fusion_of_water_at_0c + units = J kg-1 type = real | kind = kind_phys dimensions = () intent = in [ cpwv ] - standard_name = specific_heat_of_water_vapor_at_constant_pressure? + standard_name = specific_heat_of_water_vapor_at_constant_pressure units = J kg-1 K-1 type = real | kind = kind_phys dimensions = () intent = in [ cpliq ] - standard_name = specific_heat_of_liquid_water_at_20c + standard_name = specific_heat_of_liquid_water_at_constant_pressure units = J kg-1 K-1 type = real | kind = kind_phys dimensions = () intent = in [ rh2o ] - standard_name = gas_constant_of_water_vapor? - units = J kg-1 K-1? + standard_name = gas_constant_of_water_vapor + units = J kg-1 K-1 type = real | kind = kind_phys dimensions = () intent = in +[ lat ] + standard_name = latitude + units = rad + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent) + intent = in +[ long ] + standard_name = longitude + units = rad + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent) + intent = in [ t ] standard_name = air_temperature units = K type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ qh ] standard_name = water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water + advected = true units = kg kg-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in + advected = true [ prec ] standard_name = lwe_precipitation_rate_at_surface_due_to_deep_convection units = m s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = out [ pblh ] standard_name = atmosphere_boundary_layer_thickness units = m type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in [ zm ] standard_name = geopotential_height_wrt_surface units = m type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ geos ] standard_name = surface_geopotential units = m2 s-2 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in [ zi ] standard_name = geopotential_height_wrt_surface_at_interface units = m type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_interface_dimension) intent = in [ qtnd ] standard_name = tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water - units = kg kg-1 + units = kg kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out + constituent = true [ heat ] - standard_name = dry_static_energy - units = tbd + standard_name = tendency_of_dry_air_enthalpy_at_constant_pressure + units = J kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ pap ] standard_name = air_pressure units = Pa type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ paph ] standard_name = air_pressure_at_interface units = Pa type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_interface_dimension) + dimensions = (horizontal_loop_extent,vertical_interface_dimension) intent = in [ dpp ] standard_name = air_pressure_thickness units = Pa type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = in [ delt ] standard_name = timestep_for_physics @@ -288,166 +310,149 @@ dimensions = () intent = in [ mcon ] - standard_name = atmosphere_convective_mass_flux_due_to all_convection? - units = hPa s-1? + standard_name = atmosphere_convective_mass_flux_due_to_deep_convection + units = hPa s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_interface_dimension) intent = out [ cme ] - standard_name = tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water_due_to_cloud_condensation_minus_precipitation_evaporation_in_deep_convection? - units = kg kg-1 s-1? + standard_name = tendency_of_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water_from_cloud_condensation_minus_precipitation_evaporation_due_to_deep_convection + units = kg kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ cape ] - standard_name = convective_available_potential_energy? - units = J kg-1? + standard_name = zhang_mcfarlane_convective_available_potential_energy + units = J kg-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = out [ tpert ] standard_name = convective_temperature_perturbation_due_to_pbl_eddies units = K type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in [ dlf ] standard_name = detrainment_of_cloud_liquid_due_to_deep_convection units = kg kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = out +[ dif ] + standard_name = detrainment_of_cloud_ice_due_to_deep_convection + units = kg kg-1 s-1 + type = real | kind = kind_phys + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ zdu ] standard_name = detrainment_mass_flux_due_to_deep_convection - units = tbd + units = s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ rprd ] standard_name = tendency_of_precipitation_wrt_moist_air_and_condensed_water_due_to_deep_convection_excluding_subcloud_evaporation units = kg kg-1 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ mu ] standard_name = atmosphere_updraft_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = hPa s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ md ] standard_name = atmosphere_downdraft_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = hPa s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ du ] standard_name = atmosphere_detrainment_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ eu ] standard_name = atmosphere_updraft_entrainment_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ ed ] standard_name = atmosphere_downdraft_entrainment_convective_mass_flux_for_deep_convection_for_convective_columns - units = tbd + units = s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ dp ] standard_name = pressure_thickness_for_deep_convection_for_convective_columns units = hPa type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) + dimensions = (horizontal_loop_extent,vertical_layer_dimension) intent = out [ dsubcld ] standard_name = pressure_thickness_for_subcloud_layer_for_deep_convection_for_convective_columns units = hPa type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = out [ jt ] standard_name = vertical_index_at_top_of_deep_convection_for_convective_columns units = index type = integer - dimensions = (1:horizontal_loop_extent) - intent = inout + dimensions = (horizontal_loop_extent) + intent = out [ maxg ] standard_name = vertical_index_of_deep_convection_launch_level_for_convective_columns units = index type = integer - dimensions = (1:horizontal_loop_extent) - intent = inout + dimensions = (horizontal_loop_extent) + intent = out [ ideep ] standard_name = horizontal_index_of_convective_columns_for_deep_convection_for_convective_columns units = index type = integer - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = out [ ql ] standard_name = in_cloud_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water_due_to_deep_convection units = kg kg-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) - intent = inout + dimensions = (horizontal_loop_extent,vertical_layer_dimension) + intent = out [ rliq ] standard_name = vertically_integrated_cloud_liquid_tendency_due_to_all_convection_to_be_applied_later_in_time_loop units = kg m-2 s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = out [ landfrac ] standard_name = land_area_fraction - units = frac + units = fraction type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) intent = in -[ org ] - standard_name = deep_convective_organization_amount? - units = 1 - type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) - intent = in -[ orgt ] - standard_name = deep_convective_organization_amount_at_single_vertical_layer_spread_over_whole_column? - units = 1 - type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) - intent = out -[ org2d ] - standard_name = tendency_of_deep_convective_organization_amount? - units = s-1 - type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) - intent = out -[ dif ] - standard_name = detrainment_of_cloud_ice_due_to_deep_convection - units = kg kg-1 s-1 - type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) - intent = out -[ dnlf ] - standard_name = detrained_cloud_droplet_number_concentration_from_deep_convection? - units = kg-1? - type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) - intent = out -[ dnif ] - standard_name = detrained_cloud_ice_crystal_number_concentration_from_deep_convection? - units = kg-1 - type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent,1:vertical_layer_dimension) - intent = out [ rice ] standard_name = vertically_integrated_cloud_ice_tendency_due_to_all_convection_to_be_applied_later_in_time_loop - units = tbd + units = m s-1 type = real | kind = kind_phys - dimensions = (1:horizontal_loop_extent) + dimensions = (horizontal_loop_extent) + intent = out +[ lengath ] + standard_name = index_of_last_column_of_gathered_deep_convection_arrays + units = index + type = integer + dimensions = () + intent = out +[ scheme_name ] + standard_name = scheme_name + long_name = scheme name + units = none + type = character | kind = len=40 + dimensions = () intent = out [ errmsg ] standard_name = ccpp_error_message diff --git a/schemes/zhang_mcfarlane/zm_convr_namelist.xml b/schemes/zhang_mcfarlane/zm_convr_namelist.xml new file mode 100644 index 00000000..9f55aa8b --- /dev/null +++ b/schemes/zhang_mcfarlane/zm_convr_namelist.xml @@ -0,0 +1,195 @@ + + + + + + + + conv + zmconv_nl + cloud_condensate_to_precipitation_autoconversion_coefficient_over_land_for_zhang_mcfarlane_deep_convection_scheme + m-1 + real + kind_phys + Autoconversion coefficient over land in ZM deep convection scheme. + + 0.0075D0 + + + + + conv + zmconv_nl + cloud_condensate_to_precipitation_autoconversion_coefficient_over_ocean_for_zhang_mcfarlane_deep_convection_scheme + m-1 + real + kind_phys + Autoconversion coefficient over ocean in ZM deep convection scheme. + + 0.0300D0 + + + + + conv + zmconv_nl + number_of_negative_buoyancy_layers_allowed_before_convection_top_for_zhang_mcfarlane_deep_convection_scheme + count + integer + The number of negative buoyancy regions that are allowed before the convection top and CAPE calculations are completed. + + 5 + 1 + 1 + + + + + conv + zmconv_nl + tunable_evaporation_efficiency_over_ocean_for_zhang_mcfarlane_deep_convection_scheme + 1 + real + kind_phys + Tunable evaporation efficiency in ZM deep convection scheme. + + 5.0E-6 + + + + + conv + zmconv_nl + tunable_evaporation_efficiency_over_land_for_zhang_mcfarlane_deep_convection_scheme + 1 + real + kind_phys + Tunable evaporation efficiency for land in ZM deep convection scheme. + + 1.0E-5 + + + + + conv + zmconv_nl + flag_for_no_deep_convection_in_pbl + flag + logical + Include organization parameterization in ZM. This value is set to true automatically + if -zmconv_org is set in configure. + Default: .false., unless -zmconv_org set in configure + + + .false. + + + + + conv + zmconv_nl + momentum_transport_parameter_for_vertical_pressure_gradient_force_for_updraft_for_zhang_mcfarlane_deep_convection_scheme + 1 + real + kind_phys + + Convective momentum transport parameter (upward) + + + 0.4000D0 + 0.7000D0 + + + + + + conv + zmconv_nl + momentum_transport_parameter_for_vertical_pressure_gradient_force_for_downdraft_for_zhang_mcfarlane_deep_convection_scheme + 1 + real + kind_phys + + Convective momentum transport parameter (downward) + + + 0.4000D0 + 0.7000D0 + + + + + conv + zmconv_nl + entrainment_rate_for_cape_for_zhang_mcfarlane_deep_convection_scheme + m-1 + real + kind_phys + + Tunable entrainment rate in ZM deep convection scheme in units of (m-1). + + + -1.0E-3 + + + + + conv + zmconv_nl + parcel_temperature_perturbation_for_zhang_mcfarlane_deep_convection_scheme + flag + real + kind_phys + + Tunable parcel temperature perturbation in ZM deep convection scheme in units of (K). + + + 0.5 + + + + + conv + zmconv_nl + cape_threshold_for_zhang_mcfarlane_deep_convection_scheme + J kg-1 + real + kind_phys + + Tunable triggering threshold for convection in ZM deep scheme in units of (J kg-1). + + + 70.0 + + + + + conv + zmconv_nl + flag_for_well_mixed_pbl_parcel_property_for_zhang_mcfarlane_deep_convection_scheme + flag + logical + + Turn on ZM deep convection initial parcel properties as a function of a well mixed boundary layer + + + .false. + + + + + conv + zmconv_nl + deep_convective_adjustment_timescale_for_zhang_mcfarlane_deep_convection_scheme + s + real + kind_phys + + Convective adjustment timescale in units of (s) + + + 3600.0 + + + + diff --git a/suites/suite_cam7.xml b/suites/suite_cam7.xml index 0738218c..65cf3da3 100644 --- a/suites/suite_cam7.xml +++ b/suites/suite_cam7.xml @@ -1,7 +1,10 @@ + + + check_energy_gmean @@ -23,8 +26,45 @@ apply_heating_rate qneg geopotential_temp + + + initialize_constituents + to_be_ccppized_temporary + zm_convr + zm_convr_tendency_diagnostics + apply_heating_rate + apply_constituent_tendencies + qneg + geopotential_temp + cloud_fraction_fice + set_deep_conv_fluxes_to_general + zm_conv_evap + set_general_conv_fluxes_to_deep + zm_evap_tendency_diagnostics + apply_heating_rate + apply_constituent_tendencies + qneg + geopotential_temp + cloud_fraction_fice + zm_conv_momtran + zm_momtran_tendency_diagnostics + apply_heating_rate + apply_tendency_of_eastward_wind + apply_tendency_of_northward_wind + qneg + geopotential_temp + zm_conv_convtran + zm_tendency_diagnostics + apply_constituent_tendencies + qneg + geopotential_temp + zm_diagnostics + + + + sima_state_diagnostics @@ -46,5 +86,7 @@ sima_tend_diagnostics + + diff --git a/suites/suite_zhang_mcfarlane.xml b/suites/suite_zhang_mcfarlane.xml new file mode 100644 index 00000000..df676720 --- /dev/null +++ b/suites/suite_zhang_mcfarlane.xml @@ -0,0 +1,38 @@ + + + + + initialize_constituents + to_be_ccppized_temporary + zm_convr + zm_convr_tendency_diagnostics + apply_heating_rate + apply_constituent_tendencies + qneg + geopotential_temp + cloud_fraction_fice + set_deep_conv_fluxes_to_general + zm_conv_evap + set_general_conv_fluxes_to_deep + zm_evap_tendency_diagnostics + apply_heating_rate + apply_constituent_tendencies + qneg + geopotential_temp + cloud_fraction_fice + zm_conv_momtran + zm_momtran_tendency_diagnostics + apply_heating_rate + apply_tendency_of_eastward_wind + apply_tendency_of_northward_wind + qneg + geopotential_temp + zm_conv_convtran + zm_tendency_diagnostics + apply_constituent_tendencies + qneg + geopotential_temp + zm_diagnostics + + + diff --git a/to_be_ccppized/error_messages.F90 b/to_be_ccppized/error_messages.F90 new file mode 100644 index 00000000..a2a64bca --- /dev/null +++ b/to_be_ccppized/error_messages.F90 @@ -0,0 +1,151 @@ +module error_messages + + !----------------------------------------------------------------------- + ! + ! Purpose: + ! General purpose routines for issuing error messages. + ! + ! Author: B. Eaton + ! + !----------------------------------------------------------------------- + use cam_abortutils, only: endrun + use cam_logfile, only: iulog + + implicit none + save + private + public :: & + alloc_err, &! Issue error message after non-zero return from an allocate statement. + handle_err, &! Issue error message after non-zero return from anything + handle_ncerr ! Handle error returns from netCDF library procedures. + + ! If an error message string is not empty, abort with that string as the + ! error message. + public :: handle_errmsg + +!############################################################################## +contains +!############################################################################## + + subroutine alloc_err( istat, routine, name, nelem ) + + !----------------------------------------------------------------------- + ! Purpose: + ! Issue error message after non-zero return from an allocate statement. + ! + ! Author: B. Eaton + !----------------------------------------------------------------------- + + integer, intent(in) ::& + istat ! status from allocate statement + character(len=*), intent(in) ::& + routine, &! routine that called allocate + name ! name of array + integer, intent(in) ::& + nelem ! number of elements attempted to allocate + !----------------------------------------------------------------------- + + if ( istat .ne. 0 ) then + write(iulog,*)'ERROR trying to allocate memory in routine: ' & + //trim(routine) + write(iulog,*)' Variable name: '//trim(name) + write(iulog,*)' Number of elements: ',nelem + call endrun ('ALLOC_ERR') + end if + + return + + end subroutine alloc_err + +!############################################################################## + + subroutine handle_err( istat, msg ) + + !----------------------------------------------------------------------- + ! Purpose: + ! Issue error message after non-zero return from anything. + ! + ! Author: T. Henderson + !----------------------------------------------------------------------- + + integer, intent(in) :: istat ! status, zero = "no error" + character(len=*), intent(in) :: msg ! error message to print + !----------------------------------------------------------------------- + + if ( istat .ne. 0 ) then + call endrun (trim(msg)) + end if + + return + + end subroutine handle_err + +!############################################################################## + + subroutine handle_ncerr( ret, mes, line ) + + !----------------------------------------------------------------------- + ! Purpose: + ! Check netCDF library function return code. If error detected + ! issue error message then abort. + ! + ! Author: B. Eaton + !----------------------------------------------------------------------- + +!----------------------------------------------------------------------- + use netcdf +!----------------------------------------------------------------------- + + integer, intent(in) ::& + ret ! return code from netCDF library routine + character(len=*), intent(in) ::& + mes ! message to be printed if error detected + integer, intent(in), optional :: line + !----------------------------------------------------------------------- + + if ( ret .ne. NF90_NOERR ) then + if(present(line)) then + write(iulog,*) mes, line + else + write(iulog,*) mes + end if + write(iulog,*) nf90_strerror( ret ) + call endrun ('HANDLE_NCERR') + endif + + return + + end subroutine handle_ncerr + +!############################################################################## + + subroutine handle_errmsg(errmsg, subname, extra_msg) + + ! String that is asserted to be null. + character(len=*), intent(in) :: errmsg + ! Name of procedure generating the message. + character(len=*), intent(in), optional :: subname + ! Additional message from the procedure calling this one. + character(len=*), intent(in), optional :: extra_msg + + if (trim(errmsg) /= "") then + + if (present(extra_msg)) & + write(iulog,*) "handle_errmsg: & + &Message from caller: ",trim(extra_msg) + + if (present(subname)) then + call endrun("ERROR: handle_errmsg: "// & + trim(subname)//": "//trim(errmsg)) + else + call endrun("ERROR: handle_errmsg: "// & + "Error message received from routine: "//trim(errmsg)) + end if + + end if + + end subroutine handle_errmsg + +!############################################################################## + +end module error_messages diff --git a/to_be_ccppized/namelist_utils.F90 b/to_be_ccppized/namelist_utils.F90 new file mode 100644 index 00000000..c12dfad2 --- /dev/null +++ b/to_be_ccppized/namelist_utils.F90 @@ -0,0 +1,6 @@ +module namelist_utils + +use shr_nl_mod, only: & + find_group_name => shr_nl_find_group_name + +end module namelist_utils diff --git a/to_be_ccppized/units.F90 b/to_be_ccppized/units.F90 new file mode 100644 index 00000000..8497cbf6 --- /dev/null +++ b/to_be_ccppized/units.F90 @@ -0,0 +1,36 @@ +module units + +use shr_file_mod, only: shr_file_getUnit, shr_file_freeUnit + +implicit none +private + +public :: getunit, freeunit + +!------------------------------------------------------------------------------- +contains +!------------------------------------------------------------------------------- + +integer function getunit(iu) + + ! return an available unit number for i/o + + integer, intent(in), optional :: iu ! desired unit number + + getunit = shr_file_getUnit(iu) + +end function getunit + +!------------------------------------------------------------------------------- + +subroutine freeunit(iu) + + ! release the unit + + integer, intent(in) :: iu ! unit number to be freed + + call shr_file_freeUnit(iu) + +end subroutine freeunit + +end module units diff --git a/to_be_ccppized/wv_sat_methods.F90 b/to_be_ccppized/wv_sat_methods.F90 new file mode 100644 index 00000000..bb2ffeb4 --- /dev/null +++ b/to_be_ccppized/wv_sat_methods.F90 @@ -0,0 +1,759 @@ +module wv_sat_methods + +! This portable module contains all CAM methods for estimating +! the saturation vapor pressure of water. +! +! wv_saturation provides CAM-specific interfaces and utilities +! based on these formulae. +! +! Typical usage of this module: +! +! Init: +! call wv_sat_methods_init(r8, , errstring) +! +! Get scheme index from a name string: +! scheme_idx = wv_sat_get_scheme_idx(scheme_name) +! if (.not. wv_sat_valid_idx(scheme_idx)) +! +! Get pressures: +! es = wv_sat_svp_water(t, scheme_idx) +! es = wv_sat_svp_ice(t, scheme_idx) +! +! Use ice/water transition range: +! es = wv_sat_svp_trice(t, ttrice, scheme_idx) +! +! Note that elemental functions cannot be pointed to, nor passed +! as arguments. If you need to do either, it is recommended to +! wrap the function so that it can be given an explicit (non- +! elemental) interface. + +implicit none +private +save + +integer, parameter :: r8 = selected_real_kind(12) ! 8 byte real + +integer, parameter :: VLENS = 128 ! vector length for a GPU kernel + +real(r8) :: tmelt ! Melting point of water at 1 atm (K) +real(r8) :: h2otrip ! Triple point temperature of water (K) +real(r8) :: tboil ! Boiling point of water at 1 atm (K) + +real(r8) :: ttrice ! Ice-water transition range + +real(r8) :: epsilo ! Ice-water transition range +real(r8) :: omeps ! 1._r8 - epsilo + +! Indices representing individual schemes +integer, parameter :: Invalid_idx = -1 +integer, parameter :: GoffGratch_idx = 1 +integer, parameter :: MurphyKoop_idx = 2 +integer, parameter :: Bolton_idx = 3 + +! Index representing the current default scheme. +integer, parameter :: initial_default_idx = GoffGratch_idx +integer :: default_idx = initial_default_idx + +!$acc declare create (epsilo, tmelt, tboil, omeps, h2otrip, ttrice) + +public wv_sat_methods_init +public wv_sat_get_scheme_idx +public wv_sat_valid_idx + +public wv_sat_set_default +public wv_sat_reset_default + +public wv_sat_qsat_water, wv_sat_qsat_water_vect +public wv_sat_qsat_ice, wv_sat_qsat_ice_vect + +public wv_sat_svp_trans, wv_sat_svp_trans_vect + +! pressure -> humidity conversion +public wv_sat_svp_to_qsat, wv_sat_svp_to_qsat_vect + +! Combined qsat operations +public wv_sat_qsat_trans + +public wv_sat_svp_water, wv_sat_svp_water_vect +public wv_sat_svp_ice, wv_sat_svp_ice_vect + +contains + +!--------------------------------------------------------------------- +! ADMINISTRATIVE FUNCTIONS +!--------------------------------------------------------------------- + +! Get physical constants +subroutine wv_sat_methods_init(kind, tmelt_in, h2otrip_in, tboil_in, & + ttrice_in, epsilo_in, errstring) + integer, intent(in) :: kind + real(r8), intent(in) :: tmelt_in + real(r8), intent(in) :: h2otrip_in + real(r8), intent(in) :: tboil_in + real(r8), intent(in) :: ttrice_in + real(r8), intent(in) :: epsilo_in + character(len=*), intent(out) :: errstring + + errstring = ' ' + + if (kind /= r8) then + write(errstring,*) 'wv_sat_methods_init: ERROR: ', & + kind,' was input kind but ',r8,' is internal kind.' + return + end if + + if (ttrice_in < 0._r8) then + write(errstring,*) 'wv_sat_methods_init: ERROR: ', & + ttrice_in,' was input for ttrice, but negative range is invalid.' + return + end if + + tmelt = tmelt_in + h2otrip = h2otrip_in + tboil = tboil_in + ttrice = ttrice_in + epsilo = epsilo_in + + omeps = 1._r8 - epsilo + + !$acc update device (tmelt,h2otrip,tboil,ttrice,epsilo,omeps) + +end subroutine wv_sat_methods_init + +! Look up index by name. +pure function wv_sat_get_scheme_idx(name) result(idx) + character(len=*), intent(in) :: name + integer :: idx + + select case (name) + case("GoffGratch") + idx = GoffGratch_idx + case("MurphyKoop") + idx = MurphyKoop_idx + case("Bolton") + idx = Bolton_idx + case default + idx = Invalid_idx + end select + +end function wv_sat_get_scheme_idx + +! Check validity of an index from the above routine. +pure function wv_sat_valid_idx(idx) result(status) + integer, intent(in) :: idx + logical :: status + + status = (idx /= Invalid_idx) + +end function wv_sat_valid_idx + +! Set default scheme (otherwise, Goff & Gratch is default) +! Returns a logical representing success (.true.) or +! failure (.false.). +function wv_sat_set_default(name) result(status) + character(len=*), intent(in) :: name + logical :: status + + ! Don't want to overwrite valid default with invalid, + ! so assign to temporary and check it first. + integer :: tmp_idx + + tmp_idx = wv_sat_get_scheme_idx(name) + + status = wv_sat_valid_idx(tmp_idx) + + if (status) default_idx = tmp_idx + +end function wv_sat_set_default + +! Reset default scheme to initial value. +! The same thing can be accomplished with wv_sat_set_default; +! the real reason to provide this routine is to reset the +! module for testing purposes. +subroutine wv_sat_reset_default() + + default_idx = initial_default_idx + +end subroutine wv_sat_reset_default + +!--------------------------------------------------------------------- +! UTILITIES +!--------------------------------------------------------------------- + +! Get saturation specific humidity given pressure and SVP. +! Specific humidity is limited to range 0-1. +function wv_sat_svp_to_qsat(es, p) result(qs) + real(r8), intent(in) :: es ! SVP + real(r8), intent(in) :: p ! Current pressure. + real(r8) :: qs + + ! If pressure is less than SVP, set qs to maximum of 1. + if ( (p - es) <= 0._r8 ) then + qs = 1.0_r8 + else + qs = epsilo*es / (p - omeps*es) + end if + +end function wv_sat_svp_to_qsat + +! Get saturation specific humidity given pressure and SVP. +! Specific humidity is limited to range 0-1. +subroutine wv_sat_svp_to_qsat_vect(es, p, qs, vlen) + + integer, intent(in) :: vlen + real(r8), intent(in) :: es(vlen) ! SVP + real(r8), intent(in) :: p(vlen) ! Current pressure. + real(r8), intent(out) :: qs(vlen) + integer :: i + + ! If pressure is less than SVP, set qs to maximum of 1. + + !$acc data present (es,p,qs) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i=1,vlen + if ( (p(i) - es(i)) <= 0._r8 ) then + qs(i) = 1.0_r8 + else + qs(i) = epsilo*es(i) / (p(i) - omeps*es(i)) + end if + end do + !$acc end parallel + + !$acc end data +end subroutine wv_sat_svp_to_qsat_vect + +subroutine wv_sat_qsat_water(t, p, es, qs, idx) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate SVP over water at a given temperature, and then ! + ! calculate and return saturation specific humidity. ! + !------------------------------------------------------------------! + + ! Inputs + real(r8), intent(in) :: t ! Temperature + real(r8), intent(in) :: p ! Pressure + ! Outputs + real(r8), intent(out) :: es ! Saturation vapor pressure + real(r8), intent(out) :: qs ! Saturation specific humidity + + integer, intent(in), optional :: idx ! Scheme index + + es = wv_sat_svp_water(t, idx) + + qs = wv_sat_svp_to_qsat(es, p) + + ! Ensures returned es is consistent with limiters on qs. + es = min(es, p) + +end subroutine wv_sat_qsat_water + +subroutine wv_sat_qsat_water_vect(t, p, es, qs, vlen, idx) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate SVP over water at a given temperature, and then ! + ! calculate and return saturation specific humidity. ! + !------------------------------------------------------------------! + ! Inputs + + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) ! Temperature + real(r8), intent(in) :: p(vlen) ! Pressure + ! Outputs + real(r8), intent(out) :: es(vlen) ! Saturation vapor pressure + real(r8), intent(out) :: qs(vlen) ! Saturation specific humidity + + integer, intent(in), optional :: idx ! Scheme index + integer :: i + + !$acc data present (t,p,es,qs) + + call wv_sat_svp_water_vect(t, es, vlen, idx) + call wv_sat_svp_to_qsat_vect(es, p, qs, vlen) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i=1,vlen + ! Ensures returned es is consistent with limiters on qs. + es(i) = min(es(i), p(i)) + enddo + !$acc end parallel + + !$acc end data +end subroutine wv_sat_qsat_water_vect + +subroutine wv_sat_qsat_ice(t, p, es, qs, idx) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate SVP over ice at a given temperature, and then ! + ! calculate and return saturation specific humidity. ! + !------------------------------------------------------------------! + + ! Inputs + real(r8), intent(in) :: t ! Temperature + real(r8), intent(in) :: p ! Pressure + ! Outputs + real(r8), intent(out) :: es ! Saturation vapor pressure + real(r8), intent(out) :: qs ! Saturation specific humidity + + integer, intent(in), optional :: idx ! Scheme index + + es = wv_sat_svp_ice(t, idx) + + qs = wv_sat_svp_to_qsat(es, p) + + ! Ensures returned es is consistent with limiters on qs. + es = min(es, p) + +end subroutine wv_sat_qsat_ice + +subroutine wv_sat_qsat_ice_vect(t, p, es, qs, vlen, idx) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate SVP over ice at a given temperature, and then ! + ! calculate and return saturation specific humidity. ! + !------------------------------------------------------------------! + ! Inputs + + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) ! Temperature + real(r8), intent(in) :: p(vlen) ! Pressure + ! Outputs + real(r8), intent(out) :: es(vlen) ! Saturation vapor pressure + real(r8), intent(out) :: qs(vlen) ! Saturation specific humidity + + integer, intent(in), optional :: idx ! Scheme index + integer :: i + + !$acc data present (t,p,es,qs) + + call wv_sat_svp_ice_vect(t, es, vlen, idx) + call wv_sat_svp_to_qsat_vect(es, p, qs, vlen) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i=1,vlen + ! Ensures returned es is consistent with limiters on qs. + es(i) = min(es(i), p(i)) + enddo + !$acc end parallel + + !$acc end data +end subroutine wv_sat_qsat_ice_vect + +subroutine wv_sat_qsat_trans(t, p, es, qs, idx) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate SVP over ice at a given temperature, and then ! + ! calculate and return saturation specific humidity. ! + !------------------------------------------------------------------! + + ! Inputs + real(r8), intent(in) :: t ! Temperature + real(r8), intent(in) :: p ! Pressure + ! Outputs + real(r8), intent(out) :: es ! Saturation vapor pressure + real(r8), intent(out) :: qs ! Saturation specific humidity + + integer, intent(in), optional :: idx ! Scheme index + + es = wv_sat_svp_trans(t, idx) + + qs = wv_sat_svp_to_qsat(es, p) + + ! Ensures returned es is consistent with limiters on qs. + es = min(es, p) + +end subroutine wv_sat_qsat_trans + +!--------------------------------------------------------------------- +! SVP INTERFACE FUNCTIONS +!--------------------------------------------------------------------- + +function wv_sat_svp_water(t, idx) result(es) + real(r8), intent(in) :: t + integer, intent(in), optional :: idx + real(r8) :: es + + integer :: use_idx + + if (present(idx)) then + use_idx = idx + else + use_idx = default_idx + end if + + select case (use_idx) + case(GoffGratch_idx) + es = GoffGratch_svp_water(t) + case(MurphyKoop_idx) + es = MurphyKoop_svp_water(t) + case(Bolton_idx) + es = Bolton_svp_water(t) + end select + +end function wv_sat_svp_water + +subroutine wv_sat_svp_water_vect(t, es, vlen, idx) + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) + integer, intent(in), optional :: idx + real(r8), intent(out) :: es(vlen) + integer :: i + integer :: use_idx + + !$acc data present (t,es) + + if (present(idx)) then + use_idx = idx + else + use_idx = default_idx + end if + + select case (use_idx) + case(GoffGratch_idx) + call GoffGratch_svp_water_vect(t,es,vlen) + case(MurphyKoop_idx) + call MurphyKoop_svp_water_vect(t,es,vlen) + case(Bolton_idx) + call Bolton_svp_water_vect(t,es,vlen) + end select + + !$acc end data +end subroutine wv_sat_svp_water_vect + +function wv_sat_svp_ice(t, idx) result(es) + real(r8), intent(in) :: t + integer, intent(in), optional :: idx + real(r8) :: es + + integer :: use_idx + + if (present(idx)) then + use_idx = idx + else + use_idx = default_idx + end if + + select case (use_idx) + case(GoffGratch_idx) + es = GoffGratch_svp_ice(t) + case(MurphyKoop_idx) + es = MurphyKoop_svp_ice(t) + case(Bolton_idx) + es = Bolton_svp_water(t) + end select + +end function wv_sat_svp_ice + +subroutine wv_sat_svp_ice_vect(t, es, vlen, idx) + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) + integer, intent(in), optional :: idx + real(r8), intent(out) :: es(vlen) + integer :: i + + integer :: use_idx + + !$acc data present (t,es) + + if (present(idx)) then + use_idx = idx + else + use_idx = default_idx + end if + + select case (use_idx) + case(GoffGratch_idx) + call GoffGratch_svp_ice_vect(t,es,vlen) + case(MurphyKoop_idx) + call MurphyKoop_svp_ice_vect(t,es,vlen) + case(Bolton_idx) + call Bolton_svp_water_vect(t,es,vlen) + end select + + !$acc end data +end subroutine wv_sat_svp_ice_vect + +function wv_sat_svp_trans(t, idx) result(es) + + real(r8), intent(in) :: t + integer, intent(in), optional :: idx + real(r8) :: es + + real(r8) :: esice ! Saturation vapor pressure over ice + real(r8) :: weight ! Intermediate scratch variable for es transition + +! +! Water +! + if (t >= (tmelt - ttrice)) then + es = wv_sat_svp_water(t,idx) + else + es = 0.0_r8 + end if + +! +! Ice +! + if (t < tmelt) then + + esice = wv_sat_svp_ice(t,idx) + + if ( (tmelt - t) > ttrice ) then + weight = 1.0_r8 + else + weight = (tmelt - t)/ttrice + end if + + es = weight*esice + (1.0_r8 - weight)*es + end if + +end function wv_sat_svp_trans + +subroutine wv_sat_svp_trans_vect(t, es, vlen, idx) + + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) + integer, intent(in), optional :: idx + real(r8), intent(out) :: es(vlen) + + real(r8) :: esice(vlen) ! Saturation vapor pressure over ice + real(r8) :: weight ! Intermediate scratch variable for es transition + integer :: i + + !$acc data present (t,es) & + !$acc create (esice) + +! +! Water +! + call wv_sat_svp_water_vect(t,es,vlen,idx) + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i = 1, vlen + if (t(i) < (tmelt - ttrice)) then + es(i) = 0.0_r8 + end if + end do + !$acc end parallel +! +! Ice +! + call wv_sat_svp_ice_vect(t,esice,vlen,idx) + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i = 1, vlen + if (t(i) < tmelt) then + if ( (tmelt - t(i)) > ttrice ) then + weight = 1.0_r8 + else + weight = (tmelt - t(i))/ttrice + end if + + es(i) = weight*esice(i) + (1.0_r8 - weight)*es(i) + end if + end do + !$acc end parallel + + !$acc end data +end subroutine wv_sat_svp_trans_vect + +!--------------------------------------------------------------------- +! SVP METHODS +!--------------------------------------------------------------------- + +! Goff & Gratch (1946) + +function GoffGratch_svp_water(t) result(es) + real(r8), intent(in) :: t ! Temperature in Kelvin + real(r8) :: es ! SVP in Pa + + ! uncertain below -70 C + es = 10._r8**(-7.90298_r8*(tboil/t-1._r8)+ & + 5.02808_r8*log10(tboil/t)- & + 1.3816e-7_r8*(10._r8**(11.344_r8*(1._r8-t/tboil))-1._r8)+ & + 8.1328e-3_r8*(10._r8**(-3.49149_r8*(tboil/t-1._r8))-1._r8)+ & + log10(1013.246_r8))*100._r8 + +end function GoffGratch_svp_water + +subroutine GoffGratch_svp_water_vect(t, es, vlen) + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) ! Temperature in Kelvin + real(r8), intent(out) :: es(vlen) ! SVP in Pa + real(r8) :: log_tboil + integer :: i + + !$acc data present (t,es) + + ! Goff, J. A., and S. Gratch. “Low-Pressure Properties of Water from -160F + ! to 212F.” Trans. Am. Soc. Heat. Vent. Eng. 52 (1946): 95–121. + ! uncertain below -70 C + + log_tboil = log10(tboil) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i=1,vlen + es(i) = 10._r8**(-7.90298_r8*(tboil/t(i)-1._r8)+ & + 5.02808_r8*(log_tboil-log10(t(i)))- & + 1.3816e-7_r8*(10._r8**(11.344_r8*(1._r8-t(i)/tboil))-1._r8)+ & + 8.1328e-3_r8*(10._r8**(-3.49149_r8*(tboil/t(i)-1._r8))-1._r8)+ & + log10(1013.246_r8))*100._r8 + enddo + !$acc end parallel + + !$acc end data +end subroutine GoffGratch_svp_water_vect + +function GoffGratch_svp_ice(t) result(es) + real(r8), intent(in) :: t ! Temperature in Kelvin + real(r8) :: es ! SVP in Pa + + ! good down to -100 C + es = 10._r8**(-9.09718_r8*(h2otrip/t-1._r8)-3.56654_r8* & + log10(h2otrip/t)+0.876793_r8*(1._r8-t/h2otrip)+ & + log10(6.1071_r8))*100._r8 + +end function GoffGratch_svp_ice + +subroutine GoffGratch_svp_ice_vect(t, es, vlen) + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) ! Temperature in Kelvin + real(r8), intent(out) :: es(vlen) ! SVP in Pa + real(r8), parameter :: log_param = log10(6.1071_r8) + integer :: i + ! good down to -100 C + + !$acc data present (t,es) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i=1,vlen + es(i) = 10._r8**(-9.09718_r8*(h2otrip/t(i)-1._r8)-3.56654_r8* & + log10(h2otrip/t(i))+0.876793_r8*(1._r8-t(i)/h2otrip)+ & + log_param)*100._r8 + enddo + !$acc end parallel + + !$acc end data +end subroutine GoffGratch_svp_ice_vect + +! Murphy & Koop (2005) + +function MurphyKoop_svp_water(t) result(es) + real(r8), intent(in) :: t ! Temperature in Kelvin + real(r8) :: es ! SVP in Pa + + ! (good for 123 < T < 332 K) + es = exp(54.842763_r8 - (6763.22_r8 / t) - (4.210_r8 * log(t)) + & + (0.000367_r8 * t) + (tanh(0.0415_r8 * (t - 218.8_r8)) * & + (53.878_r8 - (1331.22_r8 / t) - (9.44523_r8 * log(t)) + & + 0.014025_r8 * t))) + +end function MurphyKoop_svp_water + +subroutine MurphyKoop_svp_water_vect(t, es, vlen) + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) ! Temperature in Kelvin + real(r8), intent(out) :: es(vlen) ! SVP in Pa + + integer :: i + ! Murphy, D. M., and T. Koop. “Review of the Vapour Pressure of Ice and + ! Supercooled Water for Atmospheric Applications.” Q. J. R. Meteorol. + ! Soc. 131, no. 608 (2005): 1539–65. 10.1256/qj.04.94 + ! (good for 123 < T < 332 K) + + !$acc data present (t,es) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i = 1, vlen + es(i) = exp(54.842763_r8 - (6763.22_r8 / t(i)) - (4.210_r8 * log(t(i))) + & + (0.000367_r8 * t(i)) + (tanh(0.0415_r8 * (t(i) - 218.8_r8)) * & + (53.878_r8 - (1331.22_r8 / t(i)) - (9.44523_r8 * log(t(i))) + & + 0.014025_r8 * t(i)))) + end do + !$acc end parallel + + !$acc end data +end subroutine MurphyKoop_svp_water_vect + +function MurphyKoop_svp_ice(t) result(es) + real(r8), intent(in) :: t ! Temperature in Kelvin + real(r8) :: es ! SVP in Pa + + ! (good down to 110 K) + es = exp(9.550426_r8 - (5723.265_r8 / t) + (3.53068_r8 * log(t)) & + - (0.00728332_r8 * t)) + +end function MurphyKoop_svp_ice + +subroutine MurphyKoop_svp_ice_vect(t, es, vlen) + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) ! Temperature in Kelvin + real(r8), intent(out) :: es(vlen) ! SVP in Pa + + integer :: i + ! (good down to 110 K) + + !$acc data present (t,es) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i = 1, vlen + es(i) = exp(9.550426_r8 - (5723.265_r8 / t(i)) + (3.53068_r8 * log(t(i))) & + - (0.00728332_r8 * t(i))) + end do + !$acc end parallel + + !$acc end data +end subroutine MurphyKoop_svp_ice_vect + +! Bolton (1980) +! zm_conv deep convection scheme contained this SVP calculation. +! It appears to be from D. Bolton, 1980, Monthly Weather Review. +! Unlike the other schemes, no distinct ice formula is associated +! with it. (However, a Bolton ice formula exists in CLUBB.) + +! The original formula used degrees C, but this function +! takes Kelvin and internally converts. + +function Bolton_svp_water(t) result(es) + real(r8),parameter :: c1 = 611.2_r8 + real(r8),parameter :: c2 = 17.67_r8 + real(r8),parameter :: c3 = 243.5_r8 + + real(r8), intent(in) :: t ! Temperature in Kelvin + real(r8) :: es ! SVP in Pa + + es = c1*exp( (c2*(t - tmelt))/((t - tmelt)+c3) ) + +end function Bolton_svp_water + +subroutine Bolton_svp_water_vect(t, es,vlen) + real(r8),parameter :: c1 = 611.2_r8 + real(r8),parameter :: c2 = 17.67_r8 + real(r8),parameter :: c3 = 243.5_r8 + + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) ! Temperature in Kelvin + real(r8), intent(out) :: es(vlen) ! SVP in Pa + + integer :: i + + !$acc data present (t,es) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i = 1, vlen + es(i) = c1*exp( (c2*(t(i) - tmelt))/((t(i) - tmelt)+c3) ) + end do + !$acc end parallel + + !$acc end data +end subroutine Bolton_svp_water_vect + +end module wv_sat_methods diff --git a/to_be_ccppized/wv_saturation.F90 b/to_be_ccppized/wv_saturation.F90 new file mode 100644 index 00000000..dcd1053e --- /dev/null +++ b/to_be_ccppized/wv_saturation.F90 @@ -0,0 +1,1485 @@ +module wv_saturation + +!--------------------------------------------------------------------! +! Module Overview: ! +! ! +! This module provides an interface to wv_sat_methods, providing ! +! saturation vapor pressure and related calculations to CAM. ! +! ! +! The original wv_saturation codes were introduced by J. J. Hack, ! +! February 1990. The code has been extensively rewritten since then, ! +! including a total refactoring in Summer 2012. ! +! ! +!--------------------------------------------------------------------! +! Methods: ! +! ! +! Pure water/ice saturation vapor pressures are calculated on the ! +! fly, with the specific method determined by a runtime option. ! +! Mixed phase SVP is interpolated from the internal table, estbl, ! +! which is created during initialization. ! +! ! +! The default method for calculating SVP is determined by a namelist ! +! option, and used whenever svp_water/ice or qsat are called. ! +! ! +!--------------------------------------------------------------------! + +use shr_kind_mod, only: r8 => shr_kind_r8 +use physconst, only: epsilo, & + latvap, & + latice, & + rh2o, & + cpair, & + tmelt, & + h2otrip + +use wv_sat_methods, only: & + svp_to_qsat => wv_sat_svp_to_qsat, & + svp_to_qsat_vect => wv_sat_svp_to_qsat_vect + +implicit none +private +save + +! Public interfaces +! Namelist, initialization, finalization +public wv_sat_readnl +public wv_sat_init +public wv_sat_final + +! Saturation vapor pressure calculations +public svp_water, svp_water_vect +public svp_ice, svp_ice_vect + +! Mixed phase (water + ice) saturation vapor pressure table lookup +public estblf + +public svp_to_qsat + +! Subroutines that return both SVP and humidity +! Optional arguments do temperature derivatives +interface qsat + module procedure qsat_line + module procedure qsat_vect + module procedure qsat_2D +end interface +public qsat ! Mixed phase +interface qsat_water + module procedure qsat_water_line + module procedure qsat_water_vect + module procedure qsat_water_2D +end interface +public qsat_water ! SVP over water only +interface qsat_ice + module procedure qsat_ice_line + module procedure qsat_ice_vect + module procedure qsat_ice_2D +end interface +public qsat_ice ! SVP over ice only + +! Wet bulb temperature solver +public :: findsp_vc, findsp + +! Data + +! This value is slightly high, but it seems to be the value for the +! steam point of water originally (and most frequently) used in the +! Goff & Gratch scheme. +real(r8), parameter :: tboil = 373.16_r8 + +! Table of saturation vapor pressure values (estbl) from tmin to +! tmax+1 Kelvin, in one degree increments. ttrice defines the +! transition region, estbl contains a combination of ice & water +! values. +! Make these public parameters in case another module wants to see the +! extent of the table. + real(r8), public, parameter :: tmin = 127.16_r8 + real(r8), public, parameter :: tmax = 375.16_r8 + + real(r8), parameter :: ttrice = 20.00_r8 ! transition range from es over H2O to es over ice + + integer :: plenest ! length of estbl + real(r8), allocatable :: estbl(:) ! table values of saturation vapor pressure + + real(r8) :: omeps ! 1.0_r8 - epsilo + + real(r8) :: c3 ! parameter used by findsp + + ! Set coefficients for polynomial approximation of difference + ! between saturation vapor press over water and saturation pressure + ! over ice for -ttrice < t < 0 (degrees C). NOTE: polynomial is + ! valid in the range -40 < t < 0 (degrees C). + real(r8) :: pcf(5) = (/ & + 5.04469588506e-01_r8, & + -5.47288442819e+00_r8, & + -3.67471858735e-01_r8, & + -8.95963532403e-03_r8, & + -7.78053686625e-05_r8 /) + +! --- Degree 6 approximation --- +! real(r8) :: pcf(6) = (/ & +! 7.63285250063e-02, & +! 5.86048427932e+00, & +! 4.38660831780e-01, & +! 1.37898276415e-02, & +! 2.14444472424e-04, & +! 1.36639103771e-06 /) + + integer, parameter :: VLENS = 128 ! vector length for a GPU kernel + + !$acc declare create (plenest,estbl,omeps,c3,pcf) + +contains + +!--------------------------------------------------------------------- +! ADMINISTRATIVE FUNCTIONS +!--------------------------------------------------------------------- + +subroutine wv_sat_readnl(nlfile) + !------------------------------------------------------------------! + ! Purpose: ! + ! Get runtime options for wv_saturation. ! + !------------------------------------------------------------------! + + use wv_sat_methods, only: wv_sat_get_scheme_idx, & + wv_sat_valid_idx, & + wv_sat_set_default + + use spmd_utils, only: masterproc + use namelist_utils, only: find_group_name + use units, only: getunit, freeunit +!CACNOTE - Bring this back in along with the mpibcast call below +! use mpishorthand + use cam_abortutils, only: endrun + + character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input + + ! Local variables + integer :: unitn, ierr + + character(len=32) :: wv_sat_scheme = "GoffGratch" + + character(len=*), parameter :: subname = 'wv_sat_readnl' + + namelist /wv_sat_nl/ wv_sat_scheme + !----------------------------------------------------------------------------- + + if (masterproc) then + unitn = getunit() + open( unitn, file=trim(nlfile), status='old' ) + call find_group_name(unitn, 'wv_sat_nl', status=ierr) + if (ierr == 0) then + read(unitn, wv_sat_nl, iostat=ierr) + if (ierr /= 0) then + call endrun(subname // ':: ERROR reading namelist') + return + end if + end if + close(unitn) + call freeunit(unitn) + + end if + +#ifdef SPMD +! call mpibcast(wv_sat_scheme, len(wv_sat_scheme) , mpichar, 0, mpicom) +#endif + + if (.not. wv_sat_set_default(wv_sat_scheme)) then + call endrun('wv_sat_readnl :: Invalid wv_sat_scheme.') + return + end if + +end subroutine wv_sat_readnl + +subroutine wv_sat_init + !------------------------------------------------------------------! + ! Purpose: ! + ! Initialize module (e.g. setting parameters, initializing the ! + ! SVP lookup table). ! + !------------------------------------------------------------------! + + use wv_sat_methods, only: wv_sat_methods_init, & + wv_sat_get_scheme_idx, & + wv_sat_valid_idx + use spmd_utils, only: masterproc + use cam_logfile, only: iulog + use cam_abortutils, only: endrun + use shr_assert_mod, only: shr_assert_in_domain + use error_messages, only: handle_errmsg + + integer :: status + + ! For wv_sat_methods error reporting. + character(len=256) :: errstring + + ! For generating internal SVP table. + real(r8) :: t ! Temperature + integer :: i ! Increment counter + + ! Precalculated because so frequently used. + omeps = 1.0_r8 - epsilo + + ! Transition range method is only valid for transition temperatures at: + ! -40 deg C < T < 0 deg C + call shr_assert_in_domain(ttrice, ge=0._r8, le=40._r8, varname="ttrice",& + msg="wv_sat_init: Invalid transition temperature range.") + +! This parameter uses a hardcoded 287.04_r8? + c3 = 287.04_r8*(7.5_r8*log(10._r8))/cpair + +! Init "methods" module containing actual SVP formulae. + + call wv_sat_methods_init(r8, tmelt, h2otrip, tboil, ttrice, & + epsilo, errstring) + + call handle_errmsg(errstring, subname="wv_sat_methods_init") + + ! Add two to make the table slightly too big, just in case. + plenest = ceiling(tmax-tmin) + 2 + + ! Allocate SVP table. + allocate(estbl(plenest), stat=status) + if (status /= 0) then + call endrun('wv_sat_init :: ERROR allocating saturation vapor pressure table') + return + end if + + do i = 1, plenest + estbl(i) = svp_trans(tmin + real(i-1,r8)) + end do + + !$acc update device (plenest,estbl,omeps,c3,pcf) + + if (masterproc) then + write(iulog,*)' *** SATURATION VAPOR PRESSURE TABLE COMPLETED ***' + end if + +end subroutine wv_sat_init + +subroutine wv_sat_final + !------------------------------------------------------------------! + ! Purpose: ! + ! Deallocate global variables in module. ! + !------------------------------------------------------------------! + use cam_abortutils, only: endrun + + integer :: status + + if (allocated(estbl)) then + + deallocate(estbl, stat=status) + + if (status /= 0) then + call endrun('wv_sat_final :: ERROR deallocating table') + return + end if + + end if + +end subroutine wv_sat_final + +!--------------------------------------------------------------------- +! DEFAULT SVP FUNCTIONS +!--------------------------------------------------------------------- + +! Compute saturation vapor pressure over water +function svp_water(t) result(es) + + use wv_sat_methods, only: & + wv_sat_svp_water + + real(r8), intent(in) :: t ! Temperature (K) + real(r8) :: es ! SVP (Pa) + + es = wv_sat_svp_water(t) + +end function svp_water + +! Compute saturation vapor pressure over water +subroutine svp_water_vect(t, es, vlen) + + use wv_sat_methods, only: & + wv_sat_svp_water_vect + + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) ! Temperature (K) + real(r8), intent(out) :: es(vlen) ! SVP (Pa) + + !$acc data copyin (t) copyout (es) + + call wv_sat_svp_water_vect(t, es, vlen) + + !$acc end data +end subroutine svp_water_vect + +! Compute saturation vapor pressure over ice +function svp_ice(t) result(es) + + use wv_sat_methods, only: & + wv_sat_svp_ice + + real(r8), intent(in) :: t ! Temperature (K) + real(r8) :: es ! SVP (Pa) + + es = wv_sat_svp_ice(t) + +end function svp_ice + +! Compute saturation vapor pressure over ice +subroutine svp_ice_vect(t, es, vlen) + + use wv_sat_methods, only: & + wv_sat_svp_ice_vect + + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) ! Temperature (K) + real(r8), intent(out) :: es(vlen) ! SVP (Pa) + + !$acc data copyin(t) copyout(es) + + call wv_sat_svp_ice_vect(t, es, vlen) + + !$acc end data +end subroutine svp_ice_vect + +! Compute saturation vapor pressure with an ice-water transition +function svp_trans(t) result(es) + + use wv_sat_methods, only: & + wv_sat_svp_trans + + real(r8), intent(in) :: t ! Temperature (K) + real(r8) :: es ! SVP (Pa) + + es = wv_sat_svp_trans(t) + +end function svp_trans + +! Compute saturation vapor pressure with an ice-water transition +subroutine svp_trans_vect(t, es, vlen) + + use wv_sat_methods, only: & + wv_sat_svp_trans_vect + + integer, intent(in) :: vlen + real(r8), intent(in) :: t(vlen) ! Temperature (K) + real(r8), intent(out) :: es(vlen) ! SVP (Pa) + + !$acc data copyin(t) copyout(es) + + call wv_sat_svp_trans_vect(t, es, vlen) + + !$acc end data +end subroutine svp_trans_vect + +!--------------------------------------------------------------------- +! UTILITIES +!--------------------------------------------------------------------- + +! Does linear interpolation from nearest values found +! in the table (estbl). +elemental function estblf(t) result(es) + + real(r8), intent(in) :: t ! Temperature + real(r8) :: es ! SVP (Pa) + + integer :: i ! Index for t in the table + real(r8) :: t_tmp ! intermediate temperature for es look-up + + real(r8) :: weight ! Weight for interpolation + + t_tmp = max(min(t,tmax)-tmin, 0._r8) ! Number of table entries above tmin + i = int(t_tmp) + 1 ! Corresponding index. + weight = t_tmp - aint(t_tmp, r8) ! Fractional part of t_tmp (for interpolation). + es = (1._r8 - weight)*estbl(i) + weight*estbl(i+1) + +end function estblf + +! Does linear interpolation from nearest values found +! in the table (estbl). +subroutine estblf_vect(t, es, vlen) + + integer, intent(in) :: vlen + real(r8), dimension(vlen), intent(in) :: t ! Temperature + real(r8), dimension(vlen), intent(out) :: es ! SVP (Pa) + + integer :: i ! Index for t in the table + integer :: j + real(r8) :: t_tmp ! intermediate temperature for es look-up + + real(r8) :: weight ! Weight for interpolation + + !$acc data present (t,es) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector private(t_tmp,weight,i) + do j = 1, vlen + t_tmp = max(min(t(j),tmax)-tmin, 0._r8) ! Number of table entries above tmin + i = int(t_tmp) + 1 ! Corresponding index. + weight = t_tmp - aint(t_tmp, r8) ! Fractional part of t_tmp (for interpolation). + es(j) = (1._r8 - weight)*estbl(i) + weight*estbl(i+1) + end do + !$acc end parallel + + !$acc end data +end subroutine estblf_vect + +! Get enthalpy based only on temperature +! and specific humidity. +elemental function tq_enthalpy(t, q, hltalt) result(enthalpy) + + real(r8), intent(in) :: t ! Temperature + real(r8), intent(in) :: q ! Specific humidity + real(r8), intent(in) :: hltalt ! Modified hlat for T derivatives + + real(r8) :: enthalpy + + enthalpy = cpair * t + hltalt * q + +end function tq_enthalpy + +! Get enthalpy based only on temperature +! and specific humidity. +subroutine tq_enthalpy_vect(t, q, hltalt, enthalpy, vlen) + + integer, intent(in) :: vlen + real(r8), dimension(vlen), intent(in) :: t ! Temperature + real(r8), dimension(vlen), intent(in) :: q ! Specific humidity + real(r8), dimension(vlen), intent(in) :: hltalt ! Modified hlat for T derivatives + + real(r8), dimension(vlen), intent(out) :: enthalpy + + integer :: i + + !$acc data present(t,q,hltalt,enthalpy) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i = 1, vlen + enthalpy(i) = cpair * t(i) + hltalt(i) * q(i) + end do + !$acc end parallel + + !$acc end data +end subroutine tq_enthalpy_vect + +!--------------------------------------------------------------------- +! LATENT HEAT OF VAPORIZATION CORRECTIONS +!--------------------------------------------------------------------- + +elemental subroutine no_ip_hltalt(t, hltalt) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate latent heat of vaporization of pure liquid water at ! + ! a given temperature. ! + !------------------------------------------------------------------! + + ! Inputs + real(r8), intent(in) :: t ! Temperature + ! Outputs + real(r8), intent(out) :: hltalt ! Appropriately modified hlat + + hltalt = latvap + + ! Account for change of latvap with t above freezing where + ! constant slope is given by -2369 j/(kg c) = cpv - cw + if (t >= tmelt) then + hltalt = hltalt - 2369.0_r8*(t-tmelt) + end if + +end subroutine no_ip_hltalt + +subroutine no_ip_hltalt_vect(t, hltalt, vlen) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate latent heat of vaporization of pure liquid water at ! + ! a given temperature. ! + !------------------------------------------------------------------! + + ! Inputs + integer, intent(in) :: vlen + real(r8), dimension(vlen), intent(in) :: t ! Temperature + ! Outputs + real(r8), dimension(vlen), intent(out) :: hltalt ! Appropriately modified hlat + + integer :: i + + !$acc data present(t,hltalt) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i = 1, vlen + hltalt(i) = latvap + ! Account for change of latvap with t above freezing where + ! constant slope is given by -2369 j/(kg c) = cpv - cw + if (t(i) >= tmelt) then + hltalt(i) = hltalt(i) - 2369.0_r8*(t(i)-tmelt) + end if + end do + !$acc end parallel + + !$acc end data +end subroutine no_ip_hltalt_vect + +elemental subroutine calc_hltalt(t, hltalt, tterm) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate latent heat of vaporization of water at a given ! + ! temperature, taking into account the ice phase if temperature ! + ! is below freezing. ! + ! Optional argument also calculates a term used to calculate ! + ! d(es)/dT within the water-ice transition range. ! + !------------------------------------------------------------------! + + ! Inputs + real(r8), intent(in) :: t ! Temperature + ! Outputs + real(r8), intent(out) :: hltalt ! Appropriately modified hlat + ! Term to account for d(es)/dT in transition region. + real(r8), intent(out), optional :: tterm + + ! Local variables + real(r8) :: tc ! Temperature in degrees C + real(r8) :: weight ! Weight for es transition from water to ice + ! Loop iterator + integer :: i + + if (present(tterm)) tterm = 0.0_r8 + + call no_ip_hltalt(t,hltalt) + if (t < tmelt) then + ! Weighting of hlat accounts for transition from water to ice. + tc = t - tmelt + + if (tc >= -ttrice) then + weight = -tc/ttrice + + ! polynomial expression approximates difference between es + ! over water and es over ice from 0 to -ttrice (C) (max of + ! ttrice is 40): required for accurate estimate of es + ! derivative in transition range from ice to water + if (present(tterm)) then + do i = size(pcf), 1, -1 + tterm = pcf(i) + tc*tterm + end do + tterm = tterm/ttrice + end if + + else + weight = 1.0_r8 + end if + + hltalt = hltalt + weight*latice + + end if + +end subroutine calc_hltalt + +subroutine calc_hltalt_vect(t, hltalt, vlen, tterm) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate latent heat of vaporization of water at a given ! + ! temperature, taking into account the ice phase if temperature ! + ! is below freezing. ! + ! Optional argument also calculates a term used to calculate ! + ! d(es)/dT within the water-ice transition range. ! + !------------------------------------------------------------------! + + ! Inputs + integer, intent(in) :: vlen + real(r8), dimension(vlen), intent(in) :: t ! Temperature + ! Outputs + real(r8), dimension(vlen), intent(out) :: hltalt ! Appropriately modified hlat + ! Term to account for d(es)/dT in transition region. + real(r8), dimension(vlen), intent(out), optional :: tterm + + ! Local variables + real(r8) :: tc ! Temperature in degrees C + real(r8) :: weight ! Weight for es transition from water to ice + logical :: present_tterm + ! Loop iterator + integer :: i, j, size_pcf + + present_tterm = present(tterm) + size_pcf = size(pcf) + + !$acc data present(t,hltalt,tterm) + + if (present_tterm) then + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i = 1, vlen + tterm(i) = 0.0_r8 + end do + !$acc end parallel + end if + + call no_ip_hltalt_vect(t,hltalt,vlen) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector private(tc,weight) + do j = 1, vlen + if (t(j) < tmelt) then + ! Weighting of hlat accounts for transition from water to ice. + tc = t(j) - tmelt + + if (tc >= -ttrice) then + weight = -tc/ttrice + + ! polynomial expression approximates difference between es + ! over water and es over ice from 0 to -ttrice (C) (max of + ! ttrice is 40): required for accurate estimate of es + ! derivative in transition range from ice to water + if (present_tterm) then + !$acc loop seq + do i = size_pcf, 1, -1 + tterm(j) = pcf(i) + tc*tterm(j) + end do + tterm(j) = tterm(j)/ttrice + end if + + else + weight = 1.0_r8 + end if + + hltalt(j) = hltalt(j) + weight*latice + + end if + end do + !$acc end parallel + + !$acc end data +end subroutine calc_hltalt_vect + +!--------------------------------------------------------------------- +! OPTIONAL OUTPUTS +!--------------------------------------------------------------------- + +! Temperature derivative outputs, for qsat_* +subroutine deriv_outputs_line(t, p, es, qs, hltalt, tterm, & + gam, dqsdt) + + ! Inputs + real(r8), intent(in) :: t ! Temperature + real(r8), intent(in) :: p ! Pressure + real(r8), intent(in) :: es ! Saturation vapor pressure + real(r8), intent(in) :: qs ! Saturation specific humidity + real(r8), intent(in) :: hltalt ! Modified latent heat + real(r8), intent(in) :: tterm ! Extra term for d(es)/dT in + ! transition region. + + ! Outputs + real(r8), intent(out), optional :: gam ! (hltalt/cpair)*(d(qs)/dt) + real(r8), intent(out), optional :: dqsdt ! (d(qs)/dt) + + ! Local variables + real(r8) :: desdt ! d(es)/dt + real(r8) :: dqsdt_loc ! local copy of dqsdt + + if (qs == 1.0_r8) then + dqsdt_loc = 0._r8 + else + desdt = hltalt*es/(rh2o*t*t) + tterm + dqsdt_loc = qs*p*desdt/(es*(p-omeps*es)) + end if + + if (present(dqsdt)) dqsdt = dqsdt_loc + if (present(gam)) gam = dqsdt_loc * (hltalt/cpair) + +end subroutine deriv_outputs_line + +! Temperature derivative outputs, for qsat_* +subroutine deriv_outputs_vect(t, p, es, qs, hltalt, tterm, vlen, & + gam, dqsdt) + + ! Inputs + integer, intent(in) :: vlen + real(r8), dimension(vlen), intent(in) :: t ! Temperature + real(r8), dimension(vlen), intent(in) :: p ! Pressure + real(r8), dimension(vlen), intent(in) :: es ! Saturation vapor pressure + real(r8), dimension(vlen), intent(in) :: qs ! Saturation specific humidity + real(r8), dimension(vlen), intent(in) :: hltalt ! Modified latent heat + real(r8), dimension(vlen), intent(in) :: tterm ! Extra term for d(es)/dT in + ! transition region. + + ! Outputs + real(r8), dimension(vlen), intent(out), optional :: gam ! (hltalt/cpair)*(d(qs)/dt) + real(r8), dimension(vlen), intent(out), optional :: dqsdt ! (d(qs)/dt) + + ! Local variables + real(r8) :: desdt ! d(es)/dt + real(r8) :: dqsdt_loc ! local copy of dqsdt + logical :: present_dqsdt, present_gam + integer :: i + + present_dqsdt = present(dqsdt) + present_gam = present(gam) + + !$acc data present(t,p,es,qs,hltalt,tterm,gam,dqsdt) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector private(dqsdt_loc,desdt) + do i = 1, vlen + if (qs(i) == 1.0_r8) then + dqsdt_loc = 0._r8 + else + desdt = hltalt(i)*es(i)/(rh2o*t(i)*t(i)) + tterm(i) + dqsdt_loc = qs(i)*p(i)*desdt/(es(i)*(p(i)-omeps*es(i))) + end if + + if (present_dqsdt) dqsdt(i) = dqsdt_loc + if (present_gam) gam(i) = dqsdt_loc * (hltalt(i)/cpair) + end do + !$acc end parallel + + !$acc end data +end subroutine deriv_outputs_vect + +!--------------------------------------------------------------------- +! QSAT (SPECIFIC HUMIDITY) PROCEDURES +!--------------------------------------------------------------------- + +subroutine qsat_line(t, p, es, qs, gam, dqsdt, enthalpy) + !------------------------------------------------------------------! + ! Purpose: ! + ! Look up and return saturation vapor pressure from precomputed ! + ! table, then calculate and return saturation specific humidity. ! + ! Optionally return various temperature derivatives or enthalpy ! + ! at saturation. ! + !------------------------------------------------------------------! + + ! Inputs + real(r8), intent(in) :: t ! Temperature + real(r8), intent(in) :: p ! Pressure + ! Outputs + real(r8), intent(out) :: es ! Saturation vapor pressure + real(r8), intent(out) :: qs ! Saturation specific humidity + + real(r8), intent(out), optional :: gam ! (l/cpair)*(d(qs)/dt) + real(r8), intent(out), optional :: dqsdt ! (d(qs)/dt) + real(r8), intent(out), optional :: enthalpy ! cpair*t + hltalt*q + + ! Local variables + real(r8) :: hltalt ! Modified latent heat for T derivatives + real(r8) :: tterm ! Account for d(es)/dT in transition region + + es = estblf(t) + + qs = svp_to_qsat(es, p) + + ! Ensures returned es is consistent with limiters on qs. + es = min(es, p) + + ! Calculate optional arguments. + if (present(gam) .or. present(dqsdt) .or. present(enthalpy)) then + + ! "generalized" analytic expression for t derivative of es + ! accurate to within 1 percent for 173.16 < t < 373.16 + call calc_hltalt(t, hltalt, tterm) + + if (present(enthalpy)) enthalpy = tq_enthalpy(t, qs, hltalt) + + call deriv_outputs_line(t, p, es, qs, hltalt, tterm, & + gam=gam, dqsdt=dqsdt) + + end if + +end subroutine qsat_line + +subroutine qsat_vect(t, p, es, qs, vlen, gam, dqsdt, enthalpy) + !------------------------------------------------------------------! + ! Purpose: ! + ! Look up and return saturation vapor pressure from precomputed ! + ! table, then calculate and return saturation specific humidity. ! + ! Optionally return various temperature derivatives or enthalpy ! + ! at saturation. ! + !------------------------------------------------------------------! + + ! Inputs + integer, intent(in) :: vlen + real(r8), dimension(vlen), intent(in) :: t ! Temperature + real(r8), dimension(vlen), intent(in) :: p ! Pressure + ! Outputs + real(r8), dimension(vlen), intent(out) :: es ! Saturation vapor pressure + real(r8), dimension(vlen), intent(out) :: qs ! Saturation specific humidity + + real(r8), dimension(vlen), intent(out), optional :: gam ! (l/cpair)*(d(qs)/dt) + real(r8), dimension(vlen), intent(out), optional :: dqsdt ! (d(qs)/dt) + real(r8), dimension(vlen), intent(out), optional :: enthalpy ! cpair*t + hltalt*q + + ! Local variables + real(r8), dimension(vlen) :: hltalt ! Modified latent heat for T derivatives + real(r8), dimension(vlen) :: tterm ! Account for d(es)/dT in transition region + integer :: i + logical :: present_gam, present_dqsdt, present_enthalpy + + present_gam = present(gam) + present_dqsdt = present(dqsdt) + present_enthalpy = present(enthalpy) + + !$acc data copyin (t,p) & + !$acc copyout (es,qs,gam,dqsdt,enthalpy) & + !$acc create (hltalt,tterm) + + call estblf_vect(t, es, vlen) + + call svp_to_qsat_vect(es, p, qs, vlen) + + ! Ensures returned es is consistent with limiters on qs. + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i = 1, vlen + es(i) = min(es(i), p(i)) + end do + !$acc end parallel + + ! Calculate optional arguments. + if (present_gam .or. present_dqsdt .or. present_enthalpy) then + + ! "generalized" analytic expression for t derivative of es + ! accurate to within 1 percent for 173.16 < t < 373.16 + call calc_hltalt_vect(t, hltalt, vlen, tterm) + + if (present_enthalpy) call tq_enthalpy_vect(t, qs, hltalt, enthalpy, vlen) + + call deriv_outputs_vect(t, p, es, qs, hltalt, tterm, vlen, & + gam=gam, dqsdt=dqsdt) + + end if + + !$acc end data +end subroutine qsat_vect + +subroutine qsat_2D(t, p, es, qs, dim1, dim2, gam, dqsdt, enthalpy) + !------------------------------------------------------------------! + ! Purpose: ! + ! Look up and return saturation vapor pressure from precomputed ! + ! table, then calculate and return saturation specific humidity. ! + ! Optionally return various temperature derivatives or enthalpy ! + ! at saturation. ! + !------------------------------------------------------------------! + + ! Inputs + integer, intent(in) :: dim1, dim2 + real(r8), dimension(dim1,dim2), intent(in) :: t ! Temperature + real(r8), dimension(dim1,dim2), intent(in) :: p ! Pressure + ! Outputs + real(r8), dimension(dim1,dim2), intent(out) :: es ! Saturation vapor pressure + real(r8), dimension(dim1,dim2), intent(out) :: qs ! Saturation specific humidity + + real(r8), dimension(dim1,dim2), intent(out), optional :: gam ! (l/cpair)*(d(qs)/dt) + real(r8), dimension(dim1,dim2), intent(out), optional :: dqsdt ! (d(qs)/dt) + real(r8), dimension(dim1,dim2), intent(out), optional :: enthalpy ! cpair*t + hltalt*q + + ! Local variables + real(r8), dimension(dim1,dim2) :: hltalt ! Modified latent heat for T derivatives + real(r8), dimension(dim1,dim2) :: tterm ! Account for d(es)/dT in transition region + integer :: i, k, vlen + logical :: present_gam, present_dqsdt, present_enthalpy + + vlen = dim1 * dim2 + present_gam = present(gam) + present_dqsdt = present(dqsdt) + present_enthalpy = present(enthalpy) + + !$acc data copyin (t,p) & + !$acc copyout (es,qs,gam,dqsdt,enthalpy) & + !$acc create (hltalt,tterm) + + call estblf_vect(t, es, vlen) + + call svp_to_qsat_vect(es, p, qs, vlen) + + ! Ensures returned es is consistent with limiters on qs. + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector collapse(2) + do k = 1, dim2 + do i = 1, dim1 + es(i,k) = min(es(i,k), p(i,k)) + end do + end do + !$acc end parallel + + ! Calculate optional arguments. + if (present_gam .or. present_dqsdt .or. present_enthalpy) then + + ! "generalized" analytic expression for t derivative of es + ! accurate to within 1 percent for 173.16 < t < 373.16 + call calc_hltalt_vect(t, hltalt, vlen, tterm) + + if (present_enthalpy) call tq_enthalpy_vect(t, qs, hltalt, enthalpy, vlen) + + call deriv_outputs_vect(t, p, es, qs, hltalt, tterm, vlen, & + gam=gam, dqsdt=dqsdt) + + end if + + !$acc end data +end subroutine qsat_2D + +subroutine qsat_water_line(t, p, es, qs, gam, dqsdt, enthalpy) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate SVP over water at a given temperature, and then ! + ! calculate and return saturation specific humidity. ! + ! Optionally return various temperature derivatives or enthalpy ! + ! at saturation. ! + !------------------------------------------------------------------! + + use wv_sat_methods, only: wv_sat_qsat_water + + ! Inputs + real(r8), intent(in) :: t ! Temperature + real(r8), intent(in) :: p ! Pressure + ! Outputs + real(r8), intent(out) :: es ! Saturation vapor pressure + real(r8), intent(out) :: qs ! Saturation specific humidity + + real(r8), intent(out), optional :: gam ! (l/cpair)*(d(qs)/dt) + real(r8), intent(out), optional :: dqsdt ! (d(qs)/dt) + real(r8), intent(out), optional :: enthalpy ! cpair*t + hltalt*q + + ! Local variables + real(r8) :: hltalt ! Modified latent heat for T derivatives + + call wv_sat_qsat_water(t, p, es, qs) + + if (present(gam) .or. present(dqsdt) .or. present(enthalpy)) then + + ! "generalized" analytic expression for t derivative of es + ! accurate to within 1 percent for 173.16 < t < 373.16 + call no_ip_hltalt(t, hltalt) + + if (present(enthalpy)) enthalpy = tq_enthalpy(t, qs, hltalt) + + ! For pure water/ice transition term is 0. + call deriv_outputs_line(t, p, es, qs, hltalt, 0._r8, & + gam=gam, dqsdt=dqsdt) + + end if + +end subroutine qsat_water_line + +subroutine qsat_water_vect(t, p, es, qs, vlen, gam, dqsdt, enthalpy) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate SVP over water at a given temperature, and then ! + ! calculate and return saturation specific humidity. ! + ! Optionally return various temperature derivatives or enthalpy ! + ! at saturation. ! + !------------------------------------------------------------------! + + use wv_sat_methods, only: wv_sat_qsat_water_vect + + ! Inputs + integer, intent(in) :: vlen + real(r8), dimension(vlen), intent(in) :: t ! Temperature + real(r8), dimension(vlen), intent(in) :: p ! Pressure + ! Outputs + real(r8), dimension(vlen), intent(out) :: es ! Saturation vapor pressure + real(r8), dimension(vlen), intent(out) :: qs ! Saturation specific humidity + + real(r8), dimension(vlen), intent(out), optional :: gam ! (l/cpair)*(d(qs)/dt) + real(r8), dimension(vlen), intent(out), optional :: dqsdt ! (d(qs)/dt) + real(r8), dimension(vlen), intent(out), optional :: enthalpy ! cpair*t + hltalt*q + + ! Local variables + real(r8), dimension(vlen) :: hltalt ! Modified latent heat for T derivatives + real(r8), dimension(vlen) :: tterm + integer :: i + logical :: present_gam, present_dqsdt, present_enthalpy + + present_gam = present(gam) + present_dqsdt = present(dqsdt) + present_enthalpy = present(enthalpy) + + !$acc data copyin (t,p) & + !$acc copyout (es,qs,gam,dqsdt,enthalpy) & + !$acc create (tterm,hltalt) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i = 1, vlen + tterm(i) = 0._r8 + end do + !$acc end parallel + + call wv_sat_qsat_water_vect(t, p, es, qs, vlen) + + if (present_gam .or. present_dqsdt .or. present_enthalpy) then + + ! "generalized" analytic expression for t derivative of es + ! accurate to within 1 percent for 173.16 < t < 373.16 + call no_ip_hltalt_vect(t, hltalt, vlen) + + if (present_enthalpy) call tq_enthalpy_vect(t, qs, hltalt, enthalpy, vlen) + + ! For pure water/ice transition term is 0. + call deriv_outputs_vect(t, p, es, qs, hltalt, tterm, vlen, & + gam=gam, dqsdt=dqsdt) + + end if + + !$acc end data +end subroutine qsat_water_vect + +subroutine qsat_water_2D(t, p, es, qs, dim1, dim2, gam, dqsdt, enthalpy) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate SVP over water at a given temperature, and then ! + ! calculate and return saturation specific humidity. ! + ! Optionally return various temperature derivatives or enthalpy ! + ! at saturation. ! + !------------------------------------------------------------------! + + use wv_sat_methods, only: wv_sat_qsat_water_vect + + ! Inputs + integer, intent(in) :: dim1, dim2 + real(r8), dimension(dim1,dim2), intent(in) :: t ! Temperature + real(r8), dimension(dim1,dim2), intent(in) :: p ! Pressure + ! Outputs + real(r8), dimension(dim1,dim2), intent(out) :: es ! Saturation vapor pressure + real(r8), dimension(dim1,dim2), intent(out) :: qs ! Saturation specific humidity + + real(r8), dimension(dim1,dim2), intent(out), optional :: gam ! (l/cpair)*(d(qs)/dt) + real(r8), dimension(dim1,dim2), intent(out), optional :: dqsdt ! (d(qs)/dt) + real(r8), dimension(dim1,dim2), intent(out), optional :: enthalpy ! cpair*t + hltalt*q + + ! Local variables + real(r8), dimension(dim1,dim2) :: hltalt ! Modified latent heat for T derivatives + real(r8), dimension(dim1,dim2) :: tterm + integer :: i, k, vlen + logical :: present_gam, present_dqsdt, present_enthalpy + + vlen = dim1 * dim2 + present_gam = present(gam) + present_dqsdt = present(dqsdt) + present_enthalpy = present(enthalpy) + + !$acc data copyin (t,p) & + !$acc copyout (es,qs,gam,dqsdt,enthalpy) & + !$acc create (hltalt,tterm) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector collapse(2) + do k = 1, dim2 + do i = 1, dim1 + tterm(i,k) = 0._r8 + end do + end do + !$acc end parallel + + call wv_sat_qsat_water_vect(t, p, es, qs, vlen) + + if (present_gam .or. present_dqsdt .or. present_enthalpy) then + + ! "generalized" analytic expression for t derivative of es + ! accurate to within 1 percent for 173.16 < t < 373.16 + call no_ip_hltalt_vect(t, hltalt, vlen) + + if (present_enthalpy) call tq_enthalpy_vect(t, qs, hltalt, enthalpy, vlen) + + ! For pure water/ice transition term is 0. + call deriv_outputs_vect(t, p, es, qs, hltalt, tterm, vlen, & + gam=gam, dqsdt=dqsdt) + + end if + + !$acc end data +end subroutine qsat_water_2D + +subroutine qsat_ice_line(t, p, es, qs, gam, dqsdt, enthalpy) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate SVP over ice at a given temperature, and then ! + ! calculate and return saturation specific humidity. ! + ! Optionally return various temperature derivatives or enthalpy ! + ! at saturation. ! + !------------------------------------------------------------------! + + use wv_sat_methods, only: wv_sat_qsat_ice + + ! Inputs + real(r8), intent(in) :: t ! Temperature + real(r8), intent(in) :: p ! Pressure + ! Outputs + real(r8), intent(out) :: es ! Saturation vapor pressure + real(r8), intent(out) :: qs ! Saturation specific humidity + + real(r8), intent(out), optional :: gam ! (l/cpair)*(d(qs)/dt) + real(r8), intent(out), optional :: dqsdt ! (d(qs)/dt) + real(r8), intent(out), optional :: enthalpy ! cpair*t + hltalt*q + + ! Local variables + real(r8) :: hltalt ! Modified latent heat for T derivatives + + call wv_sat_qsat_ice(t, p, es, qs) + + if (present(gam) .or. present(dqsdt) .or. present(enthalpy)) then + + ! For pure ice, just add latent heats. + hltalt = latvap + latice + + if (present(enthalpy)) enthalpy = tq_enthalpy(t, qs, hltalt) + + ! For pure water/ice transition term is 0. + call deriv_outputs_line(t, p, es, qs, hltalt, 0._r8, & + gam=gam, dqsdt=dqsdt) + + end if + +end subroutine qsat_ice_line + +subroutine qsat_ice_vect(t, p, es, qs, vlen, gam, dqsdt, enthalpy) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate SVP over ice at a given temperature, and then ! + ! calculate and return saturation specific humidity. ! + ! Optionally return various temperature derivatives or enthalpy ! + ! at saturation. ! + !------------------------------------------------------------------! + + use wv_sat_methods, only: wv_sat_qsat_ice_vect + + ! Inputs + integer, intent(in) :: vlen + real(r8), dimension(vlen), intent(in) :: t ! Temperature + real(r8), dimension(vlen), intent(in) :: p ! Pressure + ! Outputs + real(r8), dimension(vlen), intent(out) :: es ! Saturation vapor pressure + real(r8), dimension(vlen), intent(out) :: qs ! Saturation specific humidity + + real(r8), dimension(vlen), intent(out), optional :: gam ! (l/cpair)*(d(qs)/dt) + real(r8), dimension(vlen), intent(out), optional :: dqsdt ! (d(qs)/dt) + real(r8), dimension(vlen), intent(out), optional :: enthalpy ! cpair*t + hltalt*q + + ! Local variables + real(r8), dimension(vlen) :: hltalt ! Modified latent heat for T derivatives + real(r8), dimension(vlen) :: tterm + integer :: i + logical :: present_gam, present_dqsdt, present_enthalpy + + present_gam = present(gam) + present_dqsdt = present(dqsdt) + present_enthalpy = present(enthalpy) + + !$acc data copyin (t,p) & + !$acc copyout (es,qs,gam,dqsdt,enthalpy) & + !$acc create (hltalt,tterm) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i = 1, vlen + tterm(i) = 0._r8 + end do + !$acc end parallel + + call wv_sat_qsat_ice_vect(t, p, es, qs, vlen) + + if (present_gam .or. present_dqsdt .or. present_enthalpy) then + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector + do i = 1, vlen + ! For pure ice, just add latent heats. + hltalt(i) = latvap + latice + end do + !$acc end parallel + + if (present_enthalpy) call tq_enthalpy_vect(t, qs, hltalt, enthalpy, vlen) + + ! For pure water/ice transition term is 0. + call deriv_outputs_vect(t, p, es, qs, hltalt, tterm, vlen, & + gam=gam, dqsdt=dqsdt) + + end if + + !$acc end data +end subroutine qsat_ice_vect + +subroutine qsat_ice_2D(t, p, es, qs, dim1, dim2, gam, dqsdt, enthalpy) + !------------------------------------------------------------------! + ! Purpose: ! + ! Calculate SVP over ice at a given temperature, and then ! + ! calculate and return saturation specific humidity. ! + ! Optionally return various temperature derivatives or enthalpy ! + ! at saturation. ! + !------------------------------------------------------------------! + + use wv_sat_methods, only: wv_sat_qsat_ice_vect + + ! Inputs + integer, intent(in) :: dim1, dim2 + real(r8), dimension(dim1,dim2), intent(in) :: t ! Temperature + real(r8), dimension(dim1,dim2), intent(in) :: p ! Pressure + ! Outputs + real(r8), dimension(dim1,dim2), intent(out) :: es ! Saturation vapor pressure + real(r8), dimension(dim1,dim2), intent(out) :: qs ! Saturation specific humidity + + real(r8), dimension(dim1,dim2), intent(out), optional :: gam ! (l/cpair)*(d(qs)/dt) + real(r8), dimension(dim1,dim2), intent(out), optional :: dqsdt ! (d(qs)/dt) + real(r8), dimension(dim1,dim2), intent(out), optional :: enthalpy ! cpair*t + hltalt*q + + ! Local variables + real(r8), dimension(dim1,dim2) :: hltalt ! Modified latent heat for T derivatives + real(r8), dimension(dim1,dim2) :: tterm + integer :: i, k, vlen + logical :: present_gam, present_dqsdt, present_enthalpy + + vlen = dim1 * dim2 + present_gam = present(gam) + present_dqsdt = present(dqsdt) + present_enthalpy = present(enthalpy) + + !$acc data copyin (t,p) & + !$acc copyout (es,qs,gam,dqsdt,enthalpy) & + !$acc create (hltalt,tterm) + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector collapse(2) + do k = 1, dim2 + do i = 1, dim1 + tterm(i,k) = 0._r8 + end do + end do + !$acc end parallel + + call wv_sat_qsat_ice_vect(t, p, es, qs, vlen) + + if (present_gam .or. present_dqsdt .or. present_enthalpy) then + + !$acc parallel vector_length(VLENS) default(present) + !$acc loop gang vector collapse(2) + do k = 1, dim2 + do i = 1, dim1 + ! For pure ice, just add latent heats. + hltalt(i,k) = latvap + latice + end do + end do + !$acc end parallel + + if (present_enthalpy) call tq_enthalpy_vect(t, qs, hltalt, enthalpy, vlen) + + ! For pure water/ice transition term is 0. + call deriv_outputs_vect(t, p, es, qs, hltalt, tterm, vlen, & + gam=gam, dqsdt=dqsdt) + + end if + + !$acc end data +end subroutine qsat_ice_2D + +!--------------------------------------------------------------------- +! FINDSP (WET BULB TEMPERATURE) PROCEDURES +!--------------------------------------------------------------------- + +subroutine findsp_vc(q, t, p, use_ice, tsp, qsp) + + use cam_logfile, only: iulog + use cam_abortutils, only: endrun + + ! Wrapper for findsp which is 1D and handles the output status. + ! Changing findsp to elemental restricted debugging output. + ! If that output is needed again, it's preferable *not* to copy findsp, + ! but to change the existing version. + + ! input arguments + real(r8), intent(in) :: q(:) ! water vapor (kg/kg) + real(r8), intent(in) :: t(:) ! temperature (K) + real(r8), intent(in) :: p(:) ! pressure (Pa) + logical, intent(in) :: use_ice ! flag to include ice phase in calculations + + ! output arguments + real(r8), intent(out) :: tsp(:) ! saturation temp (K) + real(r8), intent(out) :: qsp(:) ! saturation mixing ratio (kg/kg) + + integer :: status(size(q)) ! flag representing state of output + ! 0 => Successful convergence + ! 1 => No calculation done: pressure or specific + ! humidity not within usable range + ! 2 => Run failed to converge + ! 4 => Temperature fell below minimum + ! 8 => Enthalpy not conserved + + integer :: n, i + + n = size(q) + + ! Currently, only 2 and 8 seem to be treated as fatal errors. + do i = 1,n + call findsp(q(i), t(i), p(i), use_ice, tsp(i), qsp(i), status(i)) + if (status(i) == 2) then + write(iulog,*) ' findsp not converging at i = ', i + write(iulog,*) ' t, q, p ', t(i), q(i), p(i) + write(iulog,*) ' tsp, qsp ', tsp(i), qsp(i) + call endrun ('wv_saturation::FINDSP -- not converging') + else if (status(i) == 8) then + write(iulog,*) ' the enthalpy is not conserved at i = ', i + write(iulog,*) ' t, q, p ', t(i), q(i), p(i) + write(iulog,*) ' tsp, qsp ', tsp(i), qsp(i) + call endrun ('wv_saturation::FINDSP -- enthalpy is not conserved') + endif + end do + +end subroutine findsp_vc + +subroutine findsp (q, t, p, use_ice, tsp, qsp, status) +!----------------------------------------------------------------------- +! +! Purpose: +! find the wet bulb temperature for a given t and q +! in a longitude height section +! wet bulb temp is the temperature and spec humidity that is +! just saturated and has the same enthalpy +! if q > qs(t) then tsp > t and qsp = qs(tsp) < q +! if q < qs(t) then tsp < t and qsp = qs(tsp) > q +! +! Method: +! a Newton method is used +! first guess uses an algorithm provided by John Petch from the UKMO +! we exclude points where the physical situation is unrealistic +! e.g. where the temperature is outside the range of validity for the +! saturation vapor pressure, or where the water vapor pressure +! exceeds the ambient pressure, or the saturation specific humidity is +! unrealistic +! +! Author: P. Rasch +! +!----------------------------------------------------------------------- +! +! input arguments +! + + real(r8), intent(in) :: q ! water vapor (kg/kg) + real(r8), intent(in) :: t ! temperature (K) + real(r8), intent(in) :: p ! pressure (Pa) + logical, intent(in) :: use_ice ! flag to include ice phase in calculations +! +! output arguments +! + real(r8), intent(out) :: tsp ! saturation temp (K) + real(r8), intent(out) :: qsp ! saturation mixing ratio (kg/kg) + integer, intent(out) :: status ! flag representing state of output + ! 0 => Successful convergence + ! 1 => No calculation done: pressure or specific + ! humidity not within usable range + ! 2 => Run failed to converge + ! 4 => Temperature fell below minimum + ! 8 => Enthalpy not conserved +! +! local variables +! + integer, parameter :: iter = 8 ! max number of times to iterate the calculation + integer :: l ! iterator + + real(r8) es ! sat. vapor pressure + real(r8) gam ! change in sat spec. hum. wrt temperature (times hltalt/cpair) + real(r8) dgdt ! work variable + real(r8) g ! work variable + real(r8) hltalt ! lat. heat. of vap. + real(r8) qs ! spec. hum. of water vapor + +! work variables + real(r8) t1, q1, dt, dq + real(r8) qvd + real(r8) r1b, c1, c2 + real(r8), parameter :: dttol = 1.e-4_r8 ! the relative temp error tolerance required to quit the iteration + real(r8), parameter :: dqtol = 1.e-4_r8 ! the relative moisture error tolerance required to quit the iteration + real(r8) enin, enout + + ! Saturation specific humidity at this temperature + if (use_ice) then + call qsat(t, p, es, qs) + else + call qsat_water(t, p, es, qs) + end if + + ! make sure a meaningful calculation is possible + if (p <= 5._r8*es .or. qs <= 0._r8 .or. qs >= 0.5_r8 & + .or. t < tmin .or. t > tmax) then + status = 1 + ! Keep initial parameters when conditions aren't suitable + tsp = t + qsp = q + enin = 1._r8 + enout = 1._r8 + + return + end if + + ! Prepare to iterate + status = 2 + + ! Get initial enthalpy + if (use_ice) then + call calc_hltalt(t,hltalt) + else + call no_ip_hltalt(t,hltalt) + end if + enin = tq_enthalpy(t, q, hltalt) + + ! make a guess at the wet bulb temp using a UKMO algorithm (from J. Petch) + c1 = hltalt*c3 + c2 = (t + 36._r8)**2 + r1b = c2/(c2 + c1*qs) + qvd = r1b * (q - qs) + tsp = t + ((hltalt/cpair)*qvd) + + ! Generate qsp, gam, and enout from tsp. + if (use_ice) then + call qsat(tsp, p, es, qsp, gam=gam, enthalpy=enout) + else + call qsat_water(tsp, p, es, qsp, gam=gam, enthalpy=enout) + end if + + ! iterate on first guess + do l = 1, iter + + g = enin - enout + dgdt = -cpair * (1 + gam) + + ! New tsp + t1 = tsp - g/dgdt + dt = abs(t1 - tsp)/t1 + tsp = t1 + + ! bail out if past end of temperature range + if ( tsp < tmin ) then + tsp = tmin + ! Get latent heat and set qsp to a value + ! that preserves enthalpy. + if (use_ice) then + call calc_hltalt(tsp,hltalt) + else + call no_ip_hltalt(tsp,hltalt) + end if + qsp = (enin - cpair*tsp)/hltalt + enout = tq_enthalpy(tsp, qsp, hltalt) + status = 4 + exit + end if + + ! Re-generate qsp, gam, and enout from new tsp. + if (use_ice) then + call qsat(tsp, p, es, q1, gam=gam, enthalpy=enout) + else + call qsat_water(tsp, p, es, q1, gam=gam, enthalpy=enout) + end if + dq = abs(q1 - qsp)/max(q1,1.e-12_r8) + qsp = q1 + + ! if converged at this point, exclude it from more iterations + if (dt < dttol .and. dq < dqtol) then + status = 0 + exit + endif + end do + + ! Test for enthalpy conservation + if (abs((enin-enout)/(enin+enout)) > 1.e-4_r8) status = 8 + +end subroutine findsp + +end module wv_saturation