Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions schemes/microp_aero/ccpp/hetfrz_classnuc_stub.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
! Stub for heterogeneous freezing by classical nucleation theory (hetfrz_classnuc).
!
! This scheme exists to read the use_hetfrz_classnuc namelist flag and expose it
! via its CCPP standard name so downstream schemes (e.g. nucleate_ice_ccpp,
! eventually PUMAS) can see the flag. It performs no heterogeneous-freezing
! computation -- the real hetfrz_classnuc_ccpp is not yet ported to CAM-SIMA.
!
! Safe to use with use_hetfrz_classnuc=.true. for snapshot-testing flows where
! the flag must propagate downstream; a warning is printed at init time.
module hetfrz_classnuc_stub
use ccpp_kinds, only: kind_phys

implicit none
private

public :: hetfrz_classnuc_stub_init

contains

!> \section arg_table_hetfrz_classnuc_stub_init Argument Table
!! \htmlinclude hetfrz_classnuc_stub_init.html
subroutine hetfrz_classnuc_stub_init( &
amIRoot, iulog, &
use_hetfrz_classnuc, &
errmsg, errflg)

logical, intent(in) :: amIRoot
integer, intent(in) :: iulog
logical, intent(in) :: use_hetfrz_classnuc

character(len=*), intent(out) :: errmsg
integer, intent(out) :: errflg

errmsg = ''
errflg = 0

if (amIRoot) then
if (use_hetfrz_classnuc) then
write(iulog, '(A)') 'WARNING: hetfrz_classnuc_stub: use_hetfrz_classnuc=.true., but ' // &
'heterogeneous freezing by classical nucleation theory is not yet ' // &
'implemented in CAM-SIMA (stub scheme).'
write(iulog, '(A)') 'WARNING: hetfrz_classnuc_stub: The flag is still propagated to ' // &
'downstream schemes (e.g. nucleate_ice_ccpp) via its CCPP standard ' // &
'name, but no hetfrz_classnuc computation will occur.'

! this is not intended to error out for now as the flag needs to be passed to downstream schemes
! (e.g., PUMAS) and modifies their behavior
else
write(iulog, '(A)') 'hetfrz_classnuc_stub: use_hetfrz_classnuc=.false. (stub scheme, ' // &
'no-op).'
end if
end if

end subroutine hetfrz_classnuc_stub_init

end module hetfrz_classnuc_stub
37 changes: 37 additions & 0 deletions schemes/microp_aero/ccpp/hetfrz_classnuc_stub.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[ccpp-table-properties]
name = hetfrz_classnuc_stub
type = scheme

[ccpp-arg-table]
name = hetfrz_classnuc_stub_init
type = scheme
[ amIRoot ]
standard_name = flag_for_mpi_root
units = flag
type = logical
dimensions = ()
intent = in
[ iulog ]
standard_name = log_output_unit
units = 1
type = integer
dimensions = ()
intent = in
[ use_hetfrz_classnuc ]
standard_name = do_heterogeneous_ice_nucleation
units = flag
type = logical
dimensions = ()
intent = in
[ errmsg ]
standard_name = ccpp_error_message
units = none
type = character | kind = len=*
dimensions = ()
intent = out
[ errflg ]
standard_name = ccpp_error_code
units = 1
type = integer
dimensions = ()
intent = out
28 changes: 28 additions & 0 deletions schemes/microp_aero/ccpp/hetfrz_classnuc_stub_namelist.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0"?>

<?xml-stylesheet type="text/xsl"?>

<entry_id_pg version="2.0">

<entry id="use_hetfrz_classnuc">
<type>logical</type>
<category>microphys</category>
<group>hetfrz_classnuc_nl</group>
<standard_name>do_heterogeneous_ice_nucleation</standard_name>
<units>flag</units>
<desc>
Switch to turn on heterogeneous freezing by classical nucleation theory.
Currently a stub in CAM-SIMA: the flag is propagated to downstream schemes
(nucleate_ice_ccpp, eventually PUMAS) but no hetfrz computation is performed.
Setting this to TRUE is supported for snapshot-testing flows where the flag
must match CAM; a warning is emitted at init time.
Default: FALSE; TRUE for CAM6 and CAM7.
</desc>
<values>
<value>.false.</value>
<value phys_suite="cam6">.true.</value>
<value phys_suite="cam7">.true.</value>
</values>
</entry>

</entry_id_pg>
4 changes: 2 additions & 2 deletions schemes/pumas/micro_pumas_ccpp_dimensions_post.meta
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@
kind = pumas_r8
intent = in
[numliq_tend]
standard_name = tendency_of_mass_number_concentration_of_cloud_liquid_water_wrt_moist_air_and_condensed_water
standard_name = tendency_of_mass_number_concentration_of_cloud_liquid_wrt_moist_air_and_condensed_water
long_name = mass number concentration of cloud liquid water wrt moist air and condensed water
units = kg-1 s-1
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
Expand All @@ -169,7 +169,7 @@
kind = pumas_r8
intent = in
[numice_tend]
standard_name = tendency_of_mass_number_concentration_of_cloud_ice_wrt_moist_air_and_condensed_water
standard_name = tendency_of_mass_number_concentration_of_ice_wrt_moist_air_and_condensed_water
long_name = mass number concentration of cloud ice wrt moist air and condensed water
units = kg-1 s-1
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
Expand Down
17 changes: 7 additions & 10 deletions schemes/pumas/micro_pumas_ccpp_dimensions_pre.F90
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ subroutine micro_pumas_ccpp_dimensions_pre_run(ncol, nlev, nlevp1,
pdel_in, pumas_pdel, &
pint_in, pumas_pint, &
strat_cldfrc_in, pumas_strat_cldfrc, &
strat_liq_cldfrc_in, pumas_strat_liq_cldfrc, &
strat_ice_cldfrc_in, pumas_strat_ice_cldfrc, &
pumas_strat_liq_cldfrc, &
pumas_strat_ice_cldfrc, &
qsatfac_in, pumas_qsatfac, &
naai_in, pumas_naai, &
npccn_in, pumas_npccn, &
Expand Down Expand Up @@ -147,10 +147,8 @@ subroutine micro_pumas_ccpp_dimensions_pre_run(ncol, nlev, nlevp1,
real(kind_phys), intent(in) :: strat_cldfrc_in(:, :)
real(pumas_r8), intent(out) :: pumas_strat_cldfrc(:, :)
! Stratiform cloud liquid area fraction (fraction)
real(kind_phys), intent(in) :: strat_liq_cldfrc_in(:, :)
real(pumas_r8), intent(out) :: pumas_strat_liq_cldfrc(:, :)
! Stratiform cloud ice area fraction (fraction)
real(kind_phys), intent(in) :: strat_ice_cldfrc_in(:, :)
real(pumas_r8), intent(out) :: pumas_strat_ice_cldfrc(:, :)
! Subgrid cloud water saturation scaling factor (1)
real(kind_phys), intent(in) :: qsatfac_in(:, :)
Expand Down Expand Up @@ -218,8 +216,10 @@ subroutine micro_pumas_ccpp_dimensions_pre_run(ncol, nlev, nlevp1,
pumas_pdel(:ncol,:) = real(pdel_in(:,:), pumas_r8)
pumas_pint(:ncol,:) = real(pint_in(:,:micro_nlevp1), pumas_r8)
pumas_strat_cldfrc(:ncol,:) = real(strat_cldfrc_in(:,:), pumas_r8)
pumas_strat_liq_cldfrc(:ncol,:) = real(strat_liq_cldfrc_in(:,:), pumas_r8)
pumas_strat_ice_cldfrc(:ncol,:) = real(strat_ice_cldfrc_in(:,:), pumas_r8)
! PUMAS uses total stratiform fraction for both liquid and ice stratus.
! Mirrors CAM micro_pumas_cam.F90: alst_mic => ast; aist_mic => ast.
pumas_strat_liq_cldfrc(:ncol,:) = real(strat_cldfrc_in(:,:), pumas_r8)
pumas_strat_ice_cldfrc(:ncol,:) = real(strat_cldfrc_in(:,:), pumas_r8)
Comment on lines +219 to +222

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for finding this one. That was a tricky one!

pumas_qsatfac(:ncol,:) = real(qsatfac_in(:,:), pumas_r8)
pumas_naai(:ncol,:) = real(naai_in(:,:), pumas_r8)
pumas_npccn(:ncol,:) = real(npccn_in(:,:), pumas_r8)
Expand All @@ -230,10 +230,7 @@ subroutine micro_pumas_ccpp_dimensions_pre_run(ncol, nlev, nlevp1,
pumas_effi_external(:ncol,:) = real(effi_external_in(:,:), pumas_r8)
pumas_frzcnt(:ncol,:) = real(frzcnt_in(:,:), pumas_r8)
pumas_frzdep(:ncol,:) = real(frzdep_in(:,:), pumas_r8)

pumas_naai(:,:) = 0._pumas_r8
pumas_npccn(:,:) = 0._pumas_r8
pumas_qsatfac(:,:) = 0._pumas_r8
pumas_frzimm(:ncol,:) = real(frzimm_in(:,:), pumas_r8)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you get rid of these variables being set to zero? I seem to remember needing to do that a while back for a reason.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAAI, NPCCN, and QSATFAC are required inputs passed in from microp_aero into PUMAS.

The first two don't matter for QPC7 but matter for FHISTC_LTso. They're NaNs in QPC7 but that appears to be fine.

QSATFAC's default value is 1, not 0, so if set to 0 here it will certainly introduce answer differences. See micro_pumas_cam.F90 in cam7:

   ! The null value for qsatfac is 1, not zero
   qsatfac(:ncol,:top_lev-1) = 1._r8

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I get to the diagnostic's step, will the NAAI and NPCCN need to have values if they are written out. I wish I could remember why I needed to add these.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they are inputs to PUMAS so there's no diagnostic output for NAAI and NPCCN. I don't think microp_aero writes them out either, but I can add that in my PR.

Before I lose this in the terminal scrollback, here's the dropsonde output without the fix: it can be seen that SIMA has all these set to zeroes but CAM has values being read in from the snapshot:

  [INPUTS DIFFER] micro_pumas_ccpp [step 1] (hit 0) arg pumas_qsatfac: 28188/28188 elements differ, max |diff| 1.000e+00 at (1,1): sima=0 cam=1
  [INPUTS DIFFER] micro_pumas_ccpp [step 1] (hit 0) arg pumas_naai: 812/28188 elements differ, max |diff| 1.031e+02 at (289,29): sima=0 cam=103.07385026541536
  [INPUTS DIFFER] micro_pumas_ccpp [step 1] (hit 0) arg pumas_npccn: 28188/28188 elements differ, max |diff| 3.610e+04 at (208,36): sima=0 cam=-36099.379900846732

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly, this was the section which impacted the numbers the most.


end subroutine micro_pumas_ccpp_dimensions_pre_run

Expand Down
20 changes: 2 additions & 18 deletions schemes/pumas/micro_pumas_ccpp_dimensions_pre.meta
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@
kind = pumas_r8
intent = out
[numliq_in]
standard_name = mass_number_concentration_of_cloud_liquid_water_wrt_moist_air_and_condensed_water
standard_name = mass_number_concentration_of_cloud_liquid_wrt_moist_air_and_condensed_water
long_name = mass number concentration of cloud liquid wrt moist air and condensed water of new state
units = kg-1
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
Expand All @@ -238,7 +238,7 @@
kind = pumas_r8
intent = out
[numice_in]
standard_name = mass_number_concentration_of_cloud_ice_wrt_moist_air_and_condensed_water
standard_name = mass_number_concentration_of_ice_wrt_moist_air_and_condensed_water
long_name = mass number concentration of cloud ice wrt moist air and condensed water of new state
units = kg-1
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
Expand Down Expand Up @@ -452,14 +452,6 @@
type = real
kind = pumas_r8
intent = out
[strat_liq_cldfrc_in]
standard_name = stratiform_cloud_liquid_area_fraction
long_name = stratiform cloud liquid area fraction
units = fraction
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
type = real
kind = kind_phys
intent = in
[pumas_strat_liq_cldfrc]
standard_name = pumas_stratiform_cloud_liquid_area_fraction
long_name = microphysics stratiform cloud liquid area fraction
Expand All @@ -468,14 +460,6 @@
type = real
kind = pumas_r8
intent = out
[strat_ice_cldfrc_in]
standard_name = stratiform_cloud_ice_area_fraction
long_name = stratiform cloud ice area fraction
units = fraction
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
type = real
kind = kind_phys
intent = in
[pumas_strat_ice_cldfrc]
standard_name = pumas_stratiform_cloud_ice_area_fraction
long_name = microphysics stratiform cloud ice area fraction
Expand Down
2 changes: 1 addition & 1 deletion schemes/pumas/pumas
59 changes: 59 additions & 0 deletions schemes/pumas/pumas_post_main.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
! Post-processing interstitial for PUMAS.
module pumas_post_main
implicit none
private

public :: pumas_post_main_run

contains

!> \section arg_table_pumas_post_main_run Argument Table
!! \htmlinclude pumas_post_main_run.html
subroutine pumas_post_main_run(ncol, cldice, numice, strat_cldfrc, effi, errmsg, errcode)
use ccpp_kinds, only: kind_phys
use pumas_kinds, only: pumas_r8=>kind_r8
use micro_pumas_utils, only: size_dist_param_basic, mg_ice_props, mincld, qsmall

integer, intent(in) :: ncol
real(kind_phys), dimension(:,:), intent(in) :: cldice ! updated cloud ice mixing ratio (kg/kg)
real(kind_phys), dimension(:,:), intent(in) :: numice ! updated cloud ice number concentration (kg-1)
real(kind_phys), dimension(:,:), intent(in) :: strat_cldfrc! total stratiform cloud area fraction (= ast)
real(kind_phys), dimension(:,:), intent(out) :: effi ! ice effective radius (micron)
character(len=512), intent(out) :: errmsg
integer, intent(out) :: errcode

integer :: k, nlev
real(pumas_r8) :: icimrst(ncol, size(cldice,2)) ! in-cloud (grid-mean) ice mixing ratio
real(pumas_r8) :: niic(ncol, size(cldice,2)) ! in-cloud (grid-mean) ice number conc
real(pumas_r8) :: rei(ncol, size(cldice,2)) ! ice slope param, then effective radius

errmsg = ' '
errcode = 0

nlev = size(cldice, 2)

! Ice effective radius is recomputed here from the post-microphysics
! grid-mean in-cloud ice, NOT from the raw per-substep value PUMAS returns.
! PUMAS uses the total stratiform fraction for ice cloud (icecldf = ast).
! Mirrors CAM micro_pumas_cam.F90:2677 (icimrst), :3174 (niic), :3171-3193 (rei).
icimrst(:,:) = min(real(cldice(:ncol,:), pumas_r8) / &
max(mincld, real(strat_cldfrc(:ncol,:), pumas_r8)), 0.005_pumas_r8)
niic(:,:) = real(numice(:ncol,:), pumas_r8) / &
max(mincld, real(strat_cldfrc(:ncol,:), pumas_r8))

rei(:,:) = 25._pumas_r8
do k = 1, nlev
call size_dist_param_basic(mg_ice_props, icimrst(:,k), niic(:,k), rei(:,k), ncol)
end do

where (icimrst(:,:) >= qsmall)
rei(:,:) = 1.5_pumas_r8 / rei(:,:) * 1.e6_pumas_r8
elsewhere
rei(:,:) = 25._pumas_r8
end where

effi(:ncol,:) = real(rei(:,:), kind_phys)

end subroutine pumas_post_main_run

end module pumas_post_main
64 changes: 64 additions & 0 deletions schemes/pumas/pumas_post_main.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
[ccpp-table-properties]
name = pumas_post_main
type = scheme
dependencies = pumas/micro_pumas_utils.F90

[ccpp-arg-table]
name = pumas_post_main_run
type = scheme
[ncol]
standard_name = horizontal_loop_extent
long_name = number of horizontal columns
units = count
dimensions = ()
type = integer
intent = in
[cldice]
standard_name = cloud_ice_mixing_ratio_wrt_moist_air_and_condensed_water
long_name = cloud ice mixing ratio wrt moist air and condensed water
units = kg kg-1
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
type = real
kind = kind_phys
intent = in
advected = true
[numice]
standard_name = mass_number_concentration_of_ice_wrt_moist_air_and_condensed_water
long_name = mass number concentration of cloud ice wrt moist air and condensed water
units = kg-1
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
type = real
kind = kind_phys
intent = in
advected = true
[strat_cldfrc]
standard_name = stratiform_cloud_area_fraction
long_name = stratiform cloud area fraction
units = fraction
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
type = real
kind = kind_phys
intent = in
[effi]
standard_name = effective_radius_of_stratiform_cloud_ice_particle
long_name = effective radius of stratiform cloud ice particle
units = micron
dimensions = (horizontal_loop_extent, vertical_layer_dimension)
type = real
kind = kind_phys
intent = out
[errmsg]
standard_name = ccpp_error_message
long_name = error message for error handling in CCPP
units = none
dimensions = ()
type = character
kind = len=512
intent = out
[errcode]
standard_name = ccpp_error_code
long_name = error code for error handling in CCPP
units = 1
dimensions = ()
type = integer
intent = out
Loading
Loading