diff --git a/.gitmodules b/.gitmodules
index 1809a94e55..cd36a45d2a 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -9,7 +9,7 @@
path = src/physics/carma/base
url = https://github.com/ESCOMP/CARMA_base.git
fxrequired = AlwaysRequired
- fxtag = carma4_01
+ fxtag = carma4_09
fxDONOTUSEurl = https://github.com/ESCOMP/CARMA_base.git
[submodule "pumas"]
diff --git a/bld/build-namelist b/bld/build-namelist
index 66c3574a62..29c7d6b316 100755
--- a/bld/build-namelist
+++ b/bld/build-namelist
@@ -1268,6 +1268,7 @@ if ($carma ne 'none') {
add_default($nl, 'carma_model', 'val'=>$carma);
add_default($nl, 'carma_flag', 'val'=>'.true.');
add_default($nl, 'history_carma', 'val'=>'.true.');
+ add_default($nl, 'carma_sulfnuc_method','val'=>'ZhaoTurco');
}
if ($carma eq 'bc_strat') {
add_default($nl, 'carma_do_drydep', 'val'=>'.true.');
@@ -1587,7 +1588,7 @@ if (defined $nl->get_value('prescribed_strataero_3modes')) {
# determine if prescribed stratospheric aerosol data is needed
if ( ($het_chem) || ($nl->get_value('prescribed_strataero_feedback') =~ /$TRUE/io ) ){
- if ( ($carma ne 'sulfate') && !($nl->get_value('modal_strat_sulfate') =~ /$TRUE/io) ) { # if no prognostic stratospheric aerosols
+ if ( !($nl->get_value('modal_strat_sulfate') =~ /$TRUE/io) ) { # if no prognostic stratospheric aerosols
unless (defined $nl->get_value('prescribed_strataero_type')) {
add_default($nl, 'prescribed_strataero_type','val'=>'CYCLICAL');
diff --git a/bld/namelist_files/namelist_definition.xml b/bld/namelist_files/namelist_definition.xml
index bd003c779a..013d8eecfc 100644
--- a/bld/namelist_files/namelist_definition.xml
+++ b/bld/namelist_files/namelist_definition.xml
@@ -4476,6 +4476,23 @@ is not active.
Default: none
+
+ Nucleation methods:
+ ZhaoTurco
+ Zhao, J. and Turco, R.,
+ Nucleation simulations in the wake of a jet aircraft in stratospheric flight,
+ J. Aerosol Sci., 26, 779-795, 1995,
+ https://doi.org/10.1016/0021-8502(95)00010-A
+ Vehkamaki
+ Vehkamaki, H., M. Kulmala, I. Napari, K.E.J. Lehtinen,
+ C. Timmreck, M. Noppel and A. Laaksonen, 2002,
+ An improved parameterization for sulfuric acid-water nucleation
+ rates for tropospheric and stratospheric conditions,
+ J. Geophys. Res., 107, 4622, doi:10.1029/2002jd002184
+Default: none
+
+
A fraction that scales how tight the convergence criteria are to
diff --git a/cime_config/testdefs/testlist_cam.xml b/cime_config/testdefs/testlist_cam.xml
index c95f004d25..d4fc9d40a8 100644
--- a/cime_config/testdefs/testlist_cam.xml
+++ b/cime_config/testdefs/testlist_cam.xml
@@ -582,6 +582,15 @@
+
+
+
+
+
+
+
+
+
@@ -602,7 +611,16 @@
+
+
+
+
+
+
+
+
+
@@ -614,7 +632,15 @@
-
+
+
+
+
+
+
+
+
+
@@ -625,6 +651,15 @@
+
+
+
+
+
+
+
+
+
@@ -636,6 +671,15 @@
+
+
+
+
+
+
+
+
+
@@ -647,6 +691,14 @@
+
+
+
+
+
+
+
+
@@ -655,9 +707,17 @@
-
+
+
+
+
+
+
+
+
+
@@ -669,6 +729,14 @@
+
+
+
+
+
+
+
+
@@ -680,6 +748,14 @@
+
+
+
+
+
+
+
+
@@ -691,6 +767,15 @@
+
+
+
+
+
+
+
+
+
@@ -738,6 +823,14 @@
+
+
+
+
+
+
+
+
@@ -749,6 +842,14 @@
+
+
+
+
+
+
+
+
@@ -757,28 +858,28 @@
-
+
-
-
+
-
+
-
+
+
@@ -799,6 +900,7 @@
+
@@ -809,6 +911,7 @@
+
@@ -829,6 +932,7 @@
+
@@ -839,6 +943,7 @@
+
@@ -859,6 +964,7 @@
+
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam
index cfac3a4818..9893ae9a9e 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam
@@ -6,4 +6,3 @@ pbuf_global_allocate=.false.
history_carma=.true.
fincl2 = 'CRSLERFC'
carma_do_fixedinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam
index 36487d1f35..ca4ea707ef 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam
@@ -5,7 +5,6 @@ inithist='ENDOFRUN'
pbuf_global_allocate=.false.
history_carma=.true.
carma_do_fixedinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
solar_data_type='FIXED'
solar_data_ymd=20000101
carma_emis_maxlat = 40.
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam
index f69245ce24..2a81a976e2 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam
@@ -5,7 +5,6 @@ inithist='ENDOFRUN'
pbuf_global_allocate=.false.
history_carma=.true.
carma_do_fixedinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
solar_data_type='FIXED'
solar_data_ymd=20000101
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam
index 52b192f861..d292329b4c 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam
@@ -5,7 +5,6 @@ inithist='ENDOFRUN'
pbuf_global_allocate=.false.
history_carma=.true.
carma_do_fixedinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
flbc_list = 'CCL4', 'CF2CLBR', 'CF3BR', 'CFC11', 'CFC113', 'CFC12', 'CH3BR', 'CH3CCL3', 'CH3CL', 'CH4', 'CO2', 'H2',
'HCFC22', 'N2O', 'OCS'
solar_data_type='FIXED'
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam
index b40ad17f97..3ec29d7308 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam
@@ -6,4 +6,3 @@ pbuf_global_allocate=.false.
history_carma=.true.
carma_do_fixedinit=.false.
carma_do_partialinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam
index 377cbb2295..bb1512a995 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam
@@ -5,4 +5,3 @@ inithist='ENDOFRUN'
pbuf_global_allocate=.false.
history_carma=.true.
carma_do_fixedinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam
index cfc4580f54..e3a93951a0 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam
@@ -5,7 +5,6 @@ inithist='ENDOFRUN'
pbuf_global_allocate=.false.
history_carma=.true.
carma_do_fixedinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
flbc_list = 'CCL4', 'CF2CLBR', 'CF3BR', 'CFC11', 'CFC113', 'CFC12', 'CH3BR', 'CH3CCL3', 'CH3CL', 'CH4', 'CO2', 'H2',
'HCFC22', 'N2O', 'OCS'
solar_data_type='FIXED'
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam
index 377cbb2295..bb1512a995 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam
@@ -5,4 +5,3 @@ inithist='ENDOFRUN'
pbuf_global_allocate=.false.
history_carma=.true.
carma_do_fixedinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam
index 377cbb2295..bb1512a995 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam
@@ -5,4 +5,3 @@ inithist='ENDOFRUN'
pbuf_global_allocate=.false.
history_carma=.true.
carma_do_fixedinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam
index 377cbb2295..bb1512a995 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam
@@ -5,4 +5,3 @@ inithist='ENDOFRUN'
pbuf_global_allocate=.false.
history_carma=.true.
carma_do_fixedinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam
index 377cbb2295..bb1512a995 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam
@@ -5,4 +5,3 @@ inithist='ENDOFRUN'
pbuf_global_allocate=.false.
history_carma=.true.
carma_do_fixedinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam
index 377cbb2295..bb1512a995 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam
@@ -5,4 +5,3 @@ inithist='ENDOFRUN'
pbuf_global_allocate=.false.
history_carma=.true.
carma_do_fixedinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
diff --git a/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam b/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam
index 377cbb2295..bb1512a995 100644
--- a/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam
+++ b/cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam
@@ -5,4 +5,3 @@ inithist='ENDOFRUN'
pbuf_global_allocate=.false.
history_carma=.true.
carma_do_fixedinit=.false.
-carma_reftfile="camrun.cam.r.carma_reft.nc"
diff --git a/doc/ChangeLog b/doc/ChangeLog
index fb46dbae7a..830edb9a3f 100644
--- a/doc/ChangeLog
+++ b/doc/ChangeLog
@@ -1,5 +1,139 @@
===============================================================
+Tag name: cam6_4_053
+Originator(s): fvitt
+Date: 7 Jan 2025
+One-line Summary: Update CARMA base external tag
+Github PR URL: https://github.com/ESCOMP/CAM/pull/1201
+
+Purpose of changes (include the issue number and title text for each relevant GitHub issue):
+
+ Update CARMA sectional aerosol model base external to tag carma4_09 and update existing CARMA models accordingly
+ (Update CARMA base external #1181)
+
+Describe any changes made to build system: N/A
+
+Describe any changes made to the namelist:
+ - new carma_sulfnuc_method option
+
+List any changes to the defaults for the boundary datasets: N/A
+
+Describe any substantial timing or memory changes: N/A
+
+Code reviewed by: cacraigucar
+
+List all files eliminated: N/A
+
+List all files added and what they do: N/A
+
+List all existing files that have been modified, and describe the changes:
+M .gitmodules
+ - update carma base tag
+
+M bld/build-namelist
+M bld/namelist_files/namelist_definition.xml
+ - new carma_sulfnuc_method namelist option
+
+M cime_config/testdefs/testlist_cam.xml
+ - adjustments to carma tests
+
+M cime_config/testdefs/testmods_dirs/cam/carma_dust/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/carma_meteor_impact/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/carma_meteor_smoke/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/carma_mixed_sulfate/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/carma_pmc/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/carma_sea_salt/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/carma_sulfate/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/carma_test_growth/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/carma_test_passive/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/carma_test_radiative/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/carma_test_swelling/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/carma_test_tracers/user_nl_cam
+M cime_config/testdefs/testmods_dirs/cam/carma_test_tracers2/user_nl_cam
+ - remove carma_reftfile namelist setting
+
+M src/physics/cam/carma_flags_mod.F90
+ - updates to carma runtime options
+
+M src/physics/cam/carma_intr.F90
+M src/physics/cam/physpkg.F90
+M src/physics/cam7/physpkg.F90
+ - interface changes for including pbuf
+
+M src/physics/carma/cam/carma_constants_mod.F90
+ - add MAXCLDAERDIAG
+
+M src/physics/carma/cam/carma_intr.F90
+ - add "only" to use statements
+ - add restart routines
+ - new diags flags
+ - many other updates needed for the development of trop_strat carma models
+
+M src/physics/carma/cam/carma_precision_mod.F90
+M src/physics/carma/models/bc_strat/carma_model_mod.F90
+M src/physics/carma/models/cirrus/carma_model_mod.F90
+M src/physics/carma/models/cirrus/growevapl.F90
+M src/physics/carma/models/cirrus_dust/carma_mod.F90
+M src/physics/carma/models/cirrus_dust/carma_model_mod.F90
+M src/physics/carma/models/cirrus_dust/growevapl.F90
+M src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90
+ - fix end module statements
+ - include missing real kind specifiers
+
+M src/physics/carma/models/dust/carma_model_mod.F90
+M src/physics/carma/models/meteor_impact/carma_model_mod.F90
+M src/physics/carma/models/meteor_smoke/carma_model_mod.F90
+M src/physics/carma/models/mixed_sulfate/carma_model_mod.F90
+M src/physics/carma/models/pmc/carma_model_mod.F90
+M src/physics/carma/models/pmc_sulfate/carma_model_mod.F90
+M src/physics/carma/models/sea_salt/carma_model_mod.F90
+M src/physics/carma/models/sulfate/carma_model_mod.F90
+M src/physics/carma/models/test_detrain/carma_model_mod.F90
+M src/physics/carma/models/test_growth/carma_model_mod.F90
+M src/physics/carma/models/test_passive/carma_model_mod.F90
+M src/physics/carma/models/test_radiative/carma_model_mod.F90
+M src/physics/carma/models/test_swelling/carma_model_mod.F90
+M src/physics/carma/models/test_tracers/carma_model_mod.F90
+M src/physics/carma/models/test_tracers2/carma_model_mod.F90
+M src/physics/carma/models/tholin/carma_model_mod.F90
+ - update interfaces including optics calculations
+ - include missing real kind specifiers
+
+M test/system/TR8.sh
+ - include physics/carma and subdirectories in the r8 checks
+
+If there were any failures reported from running test_driver.sh on any test
+platform, and checkin with these failures has been OK'd by the gatekeeper,
+then copy the lines from the td.*.status files for the failed tests to the
+appropriate machine below. All failed tests must be justified.
+
+derecho/intel/aux_cam:
+ FAIL ERP_Ln9.f09_f09_mg17.FCSD_HCO.derecho_intel.cam-outfrq9s COMPARE_base_rest
+ - pre-existing failure -- issue #856
+
+ FAIL SMS_D_Ln9.f19_f19_mg17.FXHIST.derecho_intel.cam-outfrq9s_amie SETUP
+ FAIL SMS_D_Ln9_P1280x1.ne0CONUSne30x8_ne0CONUSne30x8_mt12.FCHIST.derecho_intel.cam-outfrq9s SETUP
+ - pre-existing failures due to build-namelist error requiring CLM/CTSM external update.
+
+derecho/nvhpc/aux_cam:
+ FAIL ERS_Ln9.ne30pg3_ne30pg3_mg17.F2000dev.derecho_nvhpc.cam-outfrq9s_gpu_default COMPARE_base_rest
+ - pre-existing failure -- issue #1220
+
+izumi/nag/aux_cam:
+ FAIL DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae
+ - pre-existing failure -- issue #670
+
+ DIFF ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-carma_sea_salt
+ - expected differences due to updates to carma base code
+
+izumi/gnu/aux_cam: All PASS
+
+Summarize any changes to answers:
+ CARAM configurations change answers, otherwise bit-for-bit unchanged
+
+===============================================================
+===============================================================
+
Tag name: cam6_4_052
Originator(s): huebleruwm, nusbaume
Date: 6 Jan 2025
diff --git a/src/physics/cam/carma_flags_mod.F90 b/src/physics/cam/carma_flags_mod.F90
index 59fee48bf3..2ed1fcc531 100644
--- a/src/physics/cam/carma_flags_mod.F90
+++ b/src/physics/cam/carma_flags_mod.F90
@@ -11,8 +11,13 @@ module carma_flags_mod
use spmd_utils, only: masterproc
! Flags for integration with CAM Microphysics
- public carma_readnl ! read the carma namelist
-
+
+ implicit none
+ public
+
+ integer, parameter :: carma_maxdiags = 100
+ integer, protected :: carma_ndiagpkgs ! Number of diags_packages listed
+ integer, protected :: carma_ndebugpkgs ! Number of diags_packages listed
! Namelist flags
!
@@ -20,45 +25,53 @@ module carma_flags_mod
! calculations, but it will still initialize itself. This allows the same build and
! namelist to be used, but the CARMA processing diabled. Use the configure option
! -carma none to totally disable CARMA and prevent even the register from happening.
- logical, public :: carma_flag = .false. ! If .true. then turn on CARMA microphysics in CAM
- logical, public :: carma_do_aerosol = .true. ! If .true. then CARMA is processed after surface coupling
- logical, public :: carma_do_cldice = .false. ! If .true. then do cloud ice
- logical, public :: carma_do_cldliq = .false. ! If .true. then do cloud liquid
- logical, public :: carma_do_clearsky = .false. ! If .true. then do clear sky particle calculations
- logical, public :: carma_do_coag = .false. ! If .true. then do coagulation
- logical, public :: carma_do_detrain = .false. ! If .true. then do detrain
- logical, public :: carma_do_drydep = .false. ! If .true. then do dry deposition
- logical, public :: carma_do_emission = .false. ! If .true. then do emission
- logical, public :: carma_do_fixedinit= .false. ! If .true. then do fixed initialization to a reference state
- logical, public :: carma_hetchem_feedback= .false.! If .true. then CARMA sulfate surface area density used in heterogeneous chemistry
- logical, public :: carma_rad_feedback= .false. ! If .true. then CARMA sulfate mass mixing ratio & effective radius used in radiation
- logical, public :: carma_do_explised = .false. ! If .true. then do sedimentation with substepping
- logical, public :: carma_do_incloud = .false. ! If .true. then do incloud particle calculations
- logical, public :: carma_do_grow = .false. ! If .true. then do growth
- logical, public :: carma_do_optics = .false. ! If .true. then do optical properties file
- logical, public :: carma_do_partialinit= .false. ! If .true. then do initialization of coagulation to a reference state (requires fixedinit)
- logical, public :: carma_do_pheat = .false. ! If .true. then do particle heating
- logical, public :: carma_do_pheatatm = .false. ! If .true. then do particle heating of atmosphere
- logical, public :: carma_do_substep = .false. ! If .true. then do substeping
- logical, public :: carma_do_thermo = .false. ! If .true. then do solve thermodynamics equation
- logical, public :: carma_do_wetdep = .false. ! If .true. then do wet deposition
- logical, public :: carma_do_vdiff = .false. ! If .true. then do vertical brownian diffusion
- logical, public :: carma_do_vtran = .false. ! If .true. then do vertical transport
- integer, public :: carma_maxsubsteps = 1 ! Maximum number of time substeps allowed
- integer, public :: carma_minsubsteps = 1 ! Minimum number of time substeps allowed
- integer, public :: carma_maxretries = 8 ! Maximum number of time substeps allowed
- real(r8), public :: carma_conmax = 0.1_r8 ! Minumum relative concentration to consider in substep
- real(r8), public :: carma_dgc_threshold = 0.0_r8 ! When non-zero, the largest percentage change in gas concentration allowed per substep.
- real(r8), public :: carma_ds_threshold = 0.0_r8 ! When non-zero, the largest percentage change in gas saturation allowed per substep.
- real(r8), public :: carma_dt_threshold = 0.0_r8 ! When non-zero, the largest change in temperature (K) allowed per substep.
- real(r8), public :: carma_tstick = 1.0_r8 ! Thermal accommodation coefficient
- real(r8), public :: carma_gsticki = 0.93_r8 ! Growth accommodation coefficient for ice
- real(r8), public :: carma_gstickl = 1.0_r8 ! Growth accommodation coefficient for liquid
- real(r8), public :: carma_cstick = 1.0_r8 ! Coagulation accommodation coefficient
- real(r8), public :: carma_rhcrit = 1.0_r8 ! Critical relative humidity for liquid clouds
- real(r8), public :: carma_vf_const = 0.0_r8 ! If specified and non-zero, constant fall velocity for all particles [cm/s]
- character(len=256), public :: carma_reftfile = 'carma_reft.nc' ! path to the file containing the reference temperature profile
- character(len=32), public :: carma_model = "none" ! String (no spaces) that identifies the model
+ logical, protected :: carma_flag = .false. ! If .true. then turn on CARMA microphysics in CAM
+ logical, protected :: carma_do_aerosol = .true. ! If .true. then CARMA is processed after surface coupling
+ logical, protected :: carma_do_coremasscheck = .false. ! If .true. then do coremasscheck and abort model after certain subroutines
+ logical, protected :: carma_do_cldice = .false. ! If .true. then do cloud ice
+ logical, protected :: carma_do_cldliq = .false. ! If .true. then do cloud liquid
+ logical, protected :: carma_do_clearsky = .false. ! If .true. then do clear sky particle calculations
+ logical, protected :: carma_do_cloudborne = .false. ! If .true. then do then the carma groups can be cloudborne
+ logical, protected :: carma_do_coag = .false. ! If .true. then do coagulation
+ logical, protected :: carma_do_detrain = .false. ! If .true. then do detrain
+ logical, protected :: carma_do_drydep = .false. ! If .true. then do dry deposition
+ logical, protected :: carma_do_emission = .false. ! If .true. then do emission
+ logical, protected :: carma_do_fixedinit= .false. ! If .true. then do fixed initialization to a reference state
+ logical, protected :: carma_hetchem_feedback=.false.! If .true. then CARMA sulfate surface area density used in heterogeneous chemistry
+ logical, protected :: carma_rad_feedback= .false. ! If .true. then CARMA sulfate mass mixing ratio & effective radius used in radiation
+ logical, protected :: carma_do_explised = .false. ! If .true. then do sedimentation with substepping
+ logical, protected :: carma_do_incloud = .false. ! If .true. then do incloud particle calculations
+ logical, protected :: carma_do_budget_diags = .false. ! If .true. then do budget diagnostics
+ logical, protected :: carma_do_package_diags = .false. ! If .true. then do package diagnostics
+ logical, protected :: carma_do_grow = .false. ! If .true. then do growth
+ logical, protected :: carma_do_optics = .false. ! If .true. then do optical properties file
+ logical, protected :: carma_do_partialinit= .false. ! If .true. then do initialization of coagulation to a reference state (requires fixedinit)
+ logical, protected :: carma_do_pheat = .false. ! If .true. then do particle heating
+ logical, protected :: carma_do_pheatatm = .false. ! If .true. then do particle heating of atmosphere
+ logical, protected :: carma_do_substep = .false. ! If .true. then do substeping
+ logical, protected :: carma_do_thermo = .false. ! If .true. then do solve thermodynamics equation
+ logical, protected :: carma_do_wetdep = .false. ! If .true. then do wet deposition
+ logical, protected :: carma_do_vdiff = .false. ! If .true. then do vertical brownian diffusion
+ logical, protected :: carma_do_vtran = .false. ! If .true. then do vertical transport
+ integer, protected :: carma_diags_file = 0 ! Default file for diagnostic output
+ integer, protected :: carma_maxsubsteps = 1 ! Maximum number of time substeps allowed
+ integer, protected :: carma_minsubsteps = 1 ! Minimum number of time substeps allowed
+ integer, protected :: carma_maxretries = 8 ! Maximum number of time substeps allowed
+ real(r8), protected :: carma_conmax = 0.1_r8 ! Minumum relative concentration to consider in substep
+ real(r8), protected :: carma_dgc_threshold = 0.0_r8 ! When non-zero, the largest percentage change in gas concentration allowed per substep.
+ real(r8), protected :: carma_ds_threshold = 0.0_r8 ! When non-zero, the largest percentage change in gas saturation allowed per substep.
+ real(r8), protected :: carma_dt_threshold = 0.0_r8 ! When non-zero, the largest change in temperature (K) allowed per substep.
+ real(r8), protected :: carma_tstick = 1.0_r8 ! Thermal accommodation coefficient
+ real(r8), protected :: carma_gsticki = 0.93_r8 ! Growth accommodation coefficient for ice
+ real(r8), protected :: carma_gstickl = 1.0_r8 ! Growth accommodation coefficient for liquid
+ real(r8), protected :: carma_cstick = 1.0_r8 ! Coagulation accommodation coefficient
+ real(r8), protected :: carma_rhcrit = 1.0_r8 ! Critical relative humidity for liquid clouds
+ real(r8), protected :: carma_vf_const = 0.0_r8 ! If specified and non-zero, constant fall velocity for all particles [cm/s]
+ character(len=32), protected :: carma_model = "none" ! String (no spaces) that identifies the model
+ character(len=10), protected :: carma_sulfnuc_method = "none" ! Sulfate Nucleation method
+ character(len=32), protected :: carma_diags_packages(carma_maxdiags) = " " ! Names of physics packages for which diagnostic output is desired
+ character(len=12), protected :: carma_debug_packages(carma_maxdiags) = " " ! Names of physics packages for which debug output is desired
+
contains
@@ -68,30 +81,32 @@ module carma_flags_mod
!! @author Chuck Bardeen
!! @version Aug-2010
subroutine carma_readnl(nlfile)
-
+
! Read carma namelist group.
-
+
use cam_abortutils, only: endrun
use namelist_utils, only: find_group_name
- use units, only: getunit, freeunit
- use mpishorthand
+ use spmd_utils, only: mpicom, masterprocid, mpi_real8, mpi_integer, mpi_logical, mpi_character, mpi_success
use carma_model_flags_mod, only: carma_model_readnl
-
+
! args
-
+
character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input
-
+
! local vars
-
- integer :: unitn, ierr
-
+
+ integer :: unitn, ierr, i
+ character(len=*), parameter :: prefix = 'carma_readnl: '
+
! read namelist for CARMA
namelist /carma_nl/ &
carma_flag, &
carma_do_aerosol, &
+ carma_do_coremasscheck, &
carma_do_cldliq, &
carma_do_cldice, &
carma_do_clearsky, &
+ carma_do_cloudborne, &
carma_do_coag, &
carma_do_detrain, &
carma_do_drydep, &
@@ -115,7 +130,6 @@ subroutine carma_readnl(nlfile)
carma_minsubsteps, &
carma_maxretries, &
carma_model, &
- carma_reftfile, &
carma_conmax, &
carma_dgc_threshold, &
carma_ds_threshold, &
@@ -125,67 +139,136 @@ subroutine carma_readnl(nlfile)
carma_gstickl, &
carma_cstick, &
carma_rhcrit, &
- carma_vf_const
-
+ carma_vf_const, &
+ carma_sulfnuc_method, &
+ carma_do_budget_diags, &
+ carma_do_package_diags, &
+ carma_diags_packages, &
+ carma_debug_packages, &
+ carma_diags_file
+
if (masterproc) then
- unitn = getunit()
- open( unitn, file=trim(nlfile), status='old' )
+ open( newunit=unitn, file=trim(nlfile), status='old' )
call find_group_name(unitn, 'carma_nl', status=ierr)
if (ierr == 0) then
read(unitn, carma_nl, iostat=ierr)
if (ierr /= 0) then
- call endrun('carma_readnl: ERROR reading namelist')
+ call endrun(prefix//'ERROR reading namelist')
end if
end if
close(unitn)
- call freeunit(unitn)
end if
-
-#ifdef SPMD
- call mpibcast (carma_flag, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_aerosol, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_cldliq, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_cldice, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_clearsky, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_coag, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_detrain, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_drydep, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_emission, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_fixedinit, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_hetchem_feedback,1 ,mpilog, 0,mpicom)
- call mpibcast (carma_rad_feedback, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_explised, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_incloud, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_grow, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_optics, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_partialinit, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_pheat, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_pheatatm, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_substep, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_thermo, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_wetdep, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_vdiff, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_do_vtran, 1 ,mpilog, 0,mpicom)
- call mpibcast (carma_maxsubsteps, 1 ,mpiint, 0,mpicom)
- call mpibcast (carma_minsubsteps, 1 ,mpiint, 0,mpicom)
- call mpibcast (carma_maxretries, 1 ,mpiint, 0,mpicom)
- call mpibcast (carma_conmax, 1 ,mpir8, 0,mpicom)
- call mpibcast (carma_dgc_threshold, 1 ,mpir8, 0,mpicom)
- call mpibcast (carma_ds_threshold, 1 ,mpir8, 0,mpicom)
- call mpibcast (carma_dt_threshold, 1 ,mpir8, 0,mpicom)
- call mpibcast (carma_tstick, 1 ,mpir8, 0,mpicom)
- call mpibcast (carma_gsticki, 1 ,mpir8, 0,mpicom)
- call mpibcast (carma_gstickl, 1 ,mpir8, 0,mpicom)
- call mpibcast (carma_cstick, 1 ,mpir8, 0,mpicom)
- call mpibcast (carma_rhcrit, 1 ,mpir8, 0,mpicom)
- call mpibcast (carma_vf_const, 1 ,mpir8, 0,mpicom)
- call mpibcast (carma_model, len(carma_model), mpichar, 0, mpicom)
- call mpibcast (carma_reftfile, len(carma_reftfile), mpichar, 0, mpicom)
-#endif
+
+ call mpi_bcast (carma_flag, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_flag')
+ call mpi_bcast (carma_do_aerosol, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_aerosol')
+ call mpi_bcast (carma_do_coremasscheck,1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_coremasscheck')
+ call mpi_bcast (carma_do_cldliq, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_cldliq')
+ call mpi_bcast (carma_do_cldice, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_cldice')
+ call mpi_bcast (carma_do_clearsky, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_clearsky')
+ call mpi_bcast (carma_do_cloudborne, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_cloudborne')
+ call mpi_bcast (carma_do_coag, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_coag')
+ call mpi_bcast (carma_do_detrain, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_detrain')
+ call mpi_bcast (carma_do_drydep, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_drydep')
+ call mpi_bcast (carma_do_emission, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_emission')
+ call mpi_bcast (carma_do_fixedinit, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_fixedinit')
+ call mpi_bcast (carma_hetchem_feedback,1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_hetchem_feedback')
+ call mpi_bcast (carma_rad_feedback, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_rad_feedback')
+ call mpi_bcast (carma_do_explised, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_explised')
+ call mpi_bcast (carma_do_budget_diags, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_budget_diags')
+ call mpi_bcast (carma_do_package_diags,1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_package_diags')
+ call mpi_bcast (carma_do_incloud, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_incloud')
+ call mpi_bcast (carma_do_grow, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_grow')
+ call mpi_bcast (carma_do_optics, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_optics')
+ call mpi_bcast (carma_do_partialinit, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_partialinit')
+ call mpi_bcast (carma_do_pheat, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_pheat')
+ call mpi_bcast (carma_do_pheatatm, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_pheatatm')
+ call mpi_bcast (carma_do_substep, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_substep')
+ call mpi_bcast (carma_do_thermo, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_thermo')
+ call mpi_bcast (carma_do_wetdep, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_wetdep')
+ call mpi_bcast (carma_do_vdiff, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_vdiff')
+ call mpi_bcast (carma_do_vtran, 1 ,mpi_logical, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_do_vtran')
+ call mpi_bcast (carma_diags_file, 1 ,mpi_integer, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_diags_file')
+ call mpi_bcast (carma_maxsubsteps, 1 ,mpi_integer, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_maxsubsteps')
+ call mpi_bcast (carma_minsubsteps, 1 ,mpi_integer, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_minsubsteps')
+ call mpi_bcast (carma_maxretries, 1 ,mpi_integer, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_maxretries')
+ call mpi_bcast (carma_conmax, 1 ,mpi_real8, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_conmax')
+ call mpi_bcast (carma_dgc_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_dgc_threshold')
+ call mpi_bcast (carma_ds_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_ds_threshold')
+ call mpi_bcast (carma_dt_threshold, 1 ,mpi_real8, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_dt_threshold')
+ call mpi_bcast (carma_tstick, 1 ,mpi_real8, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_tstick')
+ call mpi_bcast (carma_gsticki, 1 ,mpi_real8, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_gsticki')
+ call mpi_bcast (carma_gstickl, 1 ,mpi_real8, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_gstickl')
+ call mpi_bcast (carma_cstick, 1 ,mpi_real8, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_cstick')
+ call mpi_bcast (carma_rhcrit, 1 ,mpi_real8, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_rhcrit')
+ call mpi_bcast (carma_vf_const, 1 ,mpi_real8, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_vf_const')
+ call mpi_bcast (carma_model, len(carma_model), mpi_character, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_model')
+ call mpi_bcast (carma_sulfnuc_method, len(carma_sulfnuc_method), mpi_character, masterprocid, mpicom, ierr)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_sulfnuc_method')
+ call mpibcast (carma_diags_packages, len(carma_diags_packages(1))*carma_maxdiags, mpi_character, 0, mpicom)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_diags_packages')
+ call mpibcast (carma_debug_packages, len(carma_debug_packages(1))*carma_maxdiags, mpi_character, 0, mpicom)
+ if (ierr/=mpi_success) call endrun(prefix//'mpi_bcast error : carma_debug_packages')
+
+ carma_ndiagpkgs = 0
+ do i = 1, carma_maxdiags
+ if (len_trim(carma_diags_packages(i)) > 0) then
+ carma_ndiagpkgs = carma_ndiagpkgs + 1
+ endif
+ enddo
+
+ carma_ndebugpkgs = 0
+ do i = 1, carma_maxdiags
+ if (len_trim(carma_debug_packages(i)) > 0) then
+ carma_ndebugpkgs = carma_ndebugpkgs + 1
+ endif
+ enddo
! Also cause the CARMA model flags to be read in.
call carma_model_readnl(nlfile)
-
+
end subroutine carma_readnl
end module carma_flags_mod
diff --git a/src/physics/cam/carma_intr.F90 b/src/physics/cam/carma_intr.F90
index fc09de5246..b555aaf68a 100644
--- a/src/physics/cam/carma_intr.F90
+++ b/src/physics/cam/carma_intr.F90
@@ -22,12 +22,12 @@ module carma_intr
implicit none
-
+
private
save
! Public interfaces
-
+
! CAM Physics Interface
public carma_register ! register consituents
public carma_is_active ! retrns true if this package is active (microphysics = .true.)
@@ -38,11 +38,11 @@ module carma_intr
public carma_timestep_init ! initialize timestep dependent variables
public carma_timestep_tend ! interface to tendency computation
public carma_accumulate_stats ! collect stats from all MPI tasks
-
+
! Other Microphysics
public carma_emission_tend ! calculate tendency from emission source function
public carma_wetdep_tend ! calculate tendency from wet deposition
-
+
contains
@@ -55,40 +55,41 @@ end subroutine carma_register
function carma_is_active()
implicit none
-
+
logical :: carma_is_active
-
+
carma_is_active = .false.
-
+
return
end function carma_is_active
function carma_implements_cnst(name)
implicit none
-
+
character(len=*), intent(in) :: name !! constituent name
logical :: carma_implements_cnst ! return value
carma_implements_cnst = .false.
-
+
return
end function carma_implements_cnst
-
- subroutine carma_init
+
+ subroutine carma_init(pbuf2d)
implicit none
-
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
+
return
end subroutine carma_init
subroutine carma_final
implicit none
-
+
return
end subroutine carma_final
-
+
subroutine carma_timestep_init
implicit none
@@ -103,7 +104,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
use time_manager, only: get_nstep, get_step_size, is_first_step
use camsrfexch, only: cam_in_t, cam_out_t
use scamMod, only: single_column
-
+
implicit none
type(physics_state), intent(inout) :: state !! physics state variables
@@ -114,13 +115,13 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
real(r8), intent(in), optional :: dlf(pcols,pver) !! Detraining cld H20 from convection (kg/kg/s)
real(r8), intent(inout), optional :: rliq(pcols) !! vertical integral of liquid not yet in q(ixcldliq)
- real(r8), intent(out), optional :: prec_str(pcols) !! [Total] sfc flux of precip from stratiform (m/s)
+ real(r8), intent(out), optional :: prec_str(pcols) !! [Total] sfc flux of precip from stratiform (m/s)
real(r8), intent(out), optional :: snow_str(pcols) !! [Total] sfc flux of snow from stratiform (m/s)
real(r8), intent(out), optional :: prec_sed(pcols) !! total precip from cloud sedimentation (m/s)
real(r8), intent(out), optional :: snow_sed(pcols) !! snow from cloud ice sedimentation (m/s)
real(r8), intent(in), optional :: ustar(pcols) !! friction velocity (m/s)
real(r8), intent(in), optional :: obklen(pcols) !! Obukhov length [ m ]
-
+
call physics_ptend_init(ptend,state%psetcols,'none') !Initialize an empty ptend for use with physics_update
if (present(prec_str)) prec_str(:) = 0._r8
@@ -140,27 +141,28 @@ subroutine carma_init_cnst(name, latvals, lonvals, mask, q)
real(r8), intent(in) :: lonvals(:) !! lon in degrees (ncol)
logical, intent(in) :: mask(:) !! Only initialize where .true.
real(r8), intent(out) :: q(:,:) !! mass mixing ratio
-
+
if (name == "carma") then
q = 0._r8
- end if
-
+ end if
+
return
end subroutine carma_init_cnst
- subroutine carma_emission_tend(state, ptend, cam_in, dt)
+ subroutine carma_emission_tend(state, ptend, cam_in, dt, pbuf)
use camsrfexch, only: cam_in_t
implicit none
-
+
type(physics_state), intent(in ) :: state !! physics state
type(physics_ptend), intent(inout) :: ptend !! physics state tendencies
type(cam_in_t), intent(inout) :: cam_in !! surface inputs
real(r8), intent(in) :: dt !! time step (s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
return
- end subroutine carma_emission_tend
+ end subroutine carma_emission_tend
subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out)
diff --git a/src/physics/cam/physpkg.F90 b/src/physics/cam/physpkg.F90
index 1d431b2dbb..609006e75a 100644
--- a/src/physics/cam/physpkg.F90
+++ b/src/physics/cam/physpkg.F90
@@ -855,7 +855,7 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
call aer_rad_props_init()
! initialize carma
- call carma_init()
+ call carma_init(pbuf2d)
! Prognostic chemistry.
call chem_init(phys_state,pbuf2d)
@@ -1531,7 +1531,7 @@ subroutine tphysac (ztodt, cam_in, &
if (carma_do_emission) then
! carma emissions
- call carma_emission_tend (state, ptend, cam_in, ztodt)
+ call carma_emission_tend (state, ptend, cam_in, ztodt, pbuf)
call physics_update(state, ptend, ztodt, tend)
end if
diff --git a/src/physics/cam7/physpkg.F90 b/src/physics/cam7/physpkg.F90
index ead4935939..7cc7946b9f 100644
--- a/src/physics/cam7/physpkg.F90
+++ b/src/physics/cam7/physpkg.F90
@@ -853,7 +853,7 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_in, cam_out )
call aer_rad_props_init()
! initialize carma
- call carma_init()
+ call carma_init(pbuf2d)
! Prognostic chemistry.
call chem_init(phys_state,pbuf2d)
@@ -1615,7 +1615,7 @@ subroutine tphysac (ztodt, cam_in, &
if (carma_do_emission) then
! carma emissions
- call carma_emission_tend (state, ptend, cam_in, ztodt)
+ call carma_emission_tend (state, ptend, cam_in, ztodt, pbuf)
call physics_update(state, ptend, ztodt, tend)
end if
diff --git a/src/physics/carma/base b/src/physics/carma/base
index bf165cd84e..67418505b4 160000
--- a/src/physics/carma/base
+++ b/src/physics/carma/base
@@ -1 +1 @@
-Subproject commit bf165cd84ef94087d9a5669a5ad47838ab24c0ef
+Subproject commit 67418505b48787bd305a50ffb581f98f0b466cba
diff --git a/src/physics/carma/cam/carma_constants_mod.F90 b/src/physics/carma/cam/carma_constants_mod.F90
index e7392cc6a5..c29820d382 100644
--- a/src/physics/carma/cam/carma_constants_mod.F90
+++ b/src/physics/carma/cam/carma_constants_mod.F90
@@ -119,9 +119,9 @@ module carma_constants_mod
!! NWAVE should be the total number of bands CAM supports.
integer, public, parameter :: NWAVE = nlwbands+nswbands ! Number of wavelength bands
-
-
-
+ !! The maximum number of diagnostic values that can be returned by
+ !! CARMA_CalculateCloudborneDiagnostics
+ integer, public, parameter :: MAXCLDAERDIAG = 16
!! These are constants per CARMA's definition, but are set dynamically in CAM and thus
!! can not be set as constants. They must be initialized as variables in carma_init.
@@ -147,5 +147,4 @@ module carma_constants_mod
!! Define ratio of gas constant for dry air and specific heat
real(kind=f) :: RKAPPA
-
-end module
+end module carma_constants_mod
diff --git a/src/physics/carma/cam/carma_intr.F90 b/src/physics/carma/cam/carma_intr.F90
index e726c296c9..89f7f415d6 100644
--- a/src/physics/carma/cam/carma_intr.F90
+++ b/src/physics/carma/cam/carma_intr.F90
@@ -9,39 +9,45 @@
!! @version July 2009
module carma_intr
- use carma_precision_mod
- use carma_enums_mod
- use carma_constants_mod
- use carma_types_mod
- use carma_flags_mod
- use carma_model_mod
- use carmaelement_mod
- use carmagas_mod
- use carmagroup_mod
- use carmasolute_mod
- use carmastate_mod
- use carma_mod
+ use carma_precision_mod, only: f
+ use carma_enums_mod, only: I_OPTICS_FIXED, I_OPTICS_MIXED_CORESHELL, I_OPTICS_MIXED_VOLUME, &
+ I_OPTICS_MIXED_MAXWELL, I_OPTICS_SULFATE, I_CNSTTYPE_PROGNOSTIC, I_HYBRID
+ use carma_constants_mod, only : GRAV, REARTH, WTMOL_AIR, WTMOL_H2O, R_AIR, CP, RKAPPA, NWAVE, &
+ CARMA_NAME_LEN, CARMA_SHORT_NAME_LEN, PI, CAM_FILL, RGAS, RM2CGS, RAD2DEG, CLDFRC_INCLOUD
+ use carma_types_mod, only : carma_type, carmastate_type
+ use carma_flags_mod, only : carma_flag, carma_do_fixedinit, carma_model, carma_do_wetdep, carma_do_emission, &
+ carma_do_pheat, carma_do_substep, carma_do_thermo, carma_do_cldice, carma_diags_file, &
+ carma_do_grow, carma_ndebugpkgs, carma_conmax, carma_cstick, carma_tstick, carma_vf_const, carma_sulfnuc_method, &
+ carma_rhcrit, carma_rad_feedback, carma_minsubsteps, carma_maxsubsteps, carma_gstickl, carma_gsticki, &
+ carma_maxretries, carma_dt_threshold, carma_ds_threshold, carma_do_vtran, carma_do_vdiff, carma_do_pheatatm, &
+ carma_do_partialinit, carma_do_optics, carma_do_incloud, carma_do_explised, carma_do_drydep, carma_do_detrain, &
+ carma_do_coremasscheck, carma_do_coag, carma_do_clearsky, carma_do_cldliq, carma_do_aerosol, carma_dgc_threshold
+
+ use carma_model_mod, only : NGAS, NBIN, NELEM, NGROUP, NMIE_WTP, NREFIDX, MIE_RH, NMIE_RH, NSOLUTE
+ use carma_model_mod, only : mie_rh, mie_wtp, is_convtran1, CARMAMODEL_DiagnoseBulk, CARMAMODEL_DiagnoseBins, &
+ CARMAMODEL_Detrain, CARMAMODEL_OutputDiagnostics, CARMAMODEL_CreateOpticsFile, CARMAMODEL_WetDeposition, &
+ CARMAMODEL_EmitParticle, CARMAMODEL_InitializeParticle, CARMAMODEL_DefineModel, CARMAMODEL_InitializeModel
+ use carmaelement_mod, only : CARMAELEMENT_Get
+ use carmagas_mod, only : CARMAGAS_Get
+ use carmagroup_mod, only : CARMAGROUP_Get
+ use carmastate_mod, only : CARMASTATE_CreateFromReference, CARMASTATE_SetGas, CARMASTATE_Step, CARMASTATE_GetBin, &
+ CARMASTATE_GetGas, CARMASTATE_GetState, CARMASTATE_Get, CARMASTATE_Create, CARMASTATE_SetBin, CARMASTATE_Destroy
+ use carma_mod, only : CARMA_Get, CARMA_Create, CARMA_Initialize, CARMA_Destroy
use shr_kind_mod, only: r8 => shr_kind_r8
- use spmd_utils, only: masterproc
- use pmgrid, only: plat, plev, plevp, plon
+ use spmd_utils, only: masterproc, mpicom
use ppgrid, only: pcols, pver, pverp
use ref_pres, only: pref_mid, pref_edge, pref_mid_norm, psurf_ref
use physics_types, only: physics_state, physics_ptend, physics_ptend_init, &
set_dry_to_wet, physics_state_copy
- use phys_grid, only: get_lat_all_p
- use physconst, only: avogad, cpair
+ use physconst, only: cpair
use constituents, only: pcnst, cnst_add, cnst_get_ind, &
- cnst_name, cnst_longname, cnst_type
- use chem_surfvals, only: chem_surfvals_get
+ cnst_name, cnst_longname
use cam_abortutils, only: endrun
use physics_buffer, only: physics_buffer_desc, pbuf_add_field, pbuf_old_tim_idx, &
- pbuf_get_index, pbuf_get_field, dtype_r8
-
-
-#if ( defined SPMD )
- use mpishorthand
-#endif
+ pbuf_get_index, pbuf_get_field, dtype_r8, pbuf_set_field
+ use pio, only: var_desc_t
+ use radconstants, only: nlwbands, nswbands
implicit none
@@ -61,17 +67,20 @@ module carma_intr
public carma_timestep_tend ! interface to tendency computation
public carma_accumulate_stats ! collect stats from all MPI tasks
+
! Other Microphysics
public carma_emission_tend ! calculate tendency from emission source function
public carma_wetdep_tend ! calculate tendency from wet deposition
-
+ public :: carma_restart_init
+ public :: carma_restart_write
+ public :: carma_restart_read
! Private data
! Particle Group Statistics
! Gridbox average
- integer, parameter :: NGPDIAGS = 12 ! Number of particle diagnostics ...
+ integer, parameter :: NGPDIAGS = 13 ! Number of particle diagnostics ...
integer, parameter :: GPDIAGS_ND = 1 ! Number density
integer, parameter :: GPDIAGS_AD = 2 ! Surface area density
integer, parameter :: GPDIAGS_MD = 3 ! Mass density
@@ -84,10 +93,15 @@ module carma_intr
integer, parameter :: GPDIAGS_VM = 10 ! Mass Weighted Fall Velocity
integer, parameter :: GPDIAGS_PA = 11 ! Projected Area
integer, parameter :: GPDIAGS_AR = 12 ! Area Ratio
+ integer, parameter :: GPDIAGS_VR = 13 ! Volatile Mixing Ratio
! Particle Bin (Element) Statistics
- integer, parameter :: NBNDIAGS = 1 ! Number of bin surface diagnostics ...
+ integer, parameter :: NBNDIAGS = 5 ! Number of bin surface diagnostics ...
integer, parameter :: BNDIAGS_TP = 1 ! Delta Particle Temperature [K]
+ integer, parameter :: BNDIAGS_WETR = 2 ! wet radius
+ integer, parameter :: BNDIAGS_ND = 3 ! Number density
+ integer, parameter :: BNDIAGS_RO = 4 ! particle density
+ integer, parameter :: BNDIAGS_VR = 5 ! Volatile Mixing Ratio
! Surface
integer, parameter :: NSBDIAGS = 2 ! Number of bin surface diagnostics ...
@@ -134,16 +148,19 @@ module carma_intr
! Physics Buffer Indicies
- integer :: ipbuf4gas(NGAS) ! physics buffer index for a carma gas
- integer :: ipbuf4t ! physics buffer index for a carma temperature
- integer :: ipbuf4sati(NGAS) ! physics buffer index for a carma saturation over ice
- integer :: ipbuf4satl(NGAS) ! physics buffer index for a carma saturation over liquid
+ integer :: ipbuf4gas(NGAS)=-1 ! physics buffer index for a carma gas
+ integer :: ipbuf4t=-1 ! physics buffer index for a carma temperature
+ integer :: ipbuf4sati(NGAS)=-1 ! physics buffer index for a carma saturation over ice
+ integer :: ipbuf4satl(NGAS)=-1 ! physics buffer index for a carma saturation over liquid
! Globals used for a reference atmosphere.
- real(kind=f) :: carma_t_ref(pver) ! midpoint temperature (Pa)
- real(kind=f) :: carma_h2o_ref(pver) ! h2o mmmr (kg/kg)
- real(kind=f) :: carma_h2so4_ref(pver) ! h2so4 mmr (kg/kg)
+ real(kind=f) :: carma_t_ref(pver) = -huge(1._f) ! midpoint temperature (Pa)
+ real(kind=f) :: carma_h2o_ref(pver) = -huge(1._f) ! h2o mmmr (kg/kg)
+ real(kind=f) :: carma_h2so4_ref(pver) = -huge(1._f) ! h2so4 mmr (kg/kg)
+ type(var_desc_t) :: t_ref_desc
+ type(var_desc_t) :: h2o_ref_desc
+ type(var_desc_t) :: h2so4_ref_desc
! Globals used for total statistics
real(kind=f) :: glob_max_nsubstep = 0._f
@@ -158,7 +175,6 @@ module carma_intr
real(kind=f) :: step_nsubstep = 0._f
real(kind=f) :: step_nretry = 0._f
-
contains
@@ -177,8 +193,7 @@ module carma_intr
!! @author Chuck Bardeen
!! @version May-2009
subroutine carma_register
- use radconstants, only : nswbands, nlwbands, &
- get_sw_spectral_boundaries, get_lw_spectral_boundaries
+ use radconstants, only : get_sw_spectral_boundaries, get_lw_spectral_boundaries
use cam_logfile, only : iulog
use cam_control_mod, only : initial_run
use physconst, only: gravit, p_rearth=>rearth, mwdry, mwh2o
@@ -251,19 +266,19 @@ subroutine carma_register
! Create the CARMA object that will contain all the information about the
! how CARMA is configured.
-
call CARMA_Create(carma, NBIN, NELEM, NGROUP, NSOLUTE, NGAS, NWAVE, rc, &
- LUNOPRT=LUNOPRT, wave=wave, dwave=dwave, do_wave_emit=do_wave_emit)
+ LUNOPRT=LUNOPRT, wave=wave, dwave=dwave, do_wave_emit=do_wave_emit, NREFIDX=NREFIDX)
if (rc < 0) call endrun('carma_register::CARMA_Create failed.')
! Define the microphysical model.
- call CARMA_DefineModel(carma, rc)
+ call CARMAMODEL_DefineModel(carma, rc)
if (rc < 0) call endrun('carma_register::CARMA_DefineModel failed.')
if (masterproc) then
write(LUNOPRT,*) ''
write(LUNOPRT,*) 'CARMA general settings for ', trim(carma_model), ' model : '
write(LUNOPRT,*) ' carma_do_aerosol = ', carma_do_aerosol
+ write(LUNOPRT,*) ' carma_do_coremasscheck = ',carma_do_coremasscheck
write(LUNOPRT,*) ' carma_do_cldice = ', carma_do_cldice
write(LUNOPRT,*) ' carma_do_cldliq = ', carma_do_cldliq
write(LUNOPRT,*) ' carma_do_clearsky = ', carma_do_clearsky
@@ -297,8 +312,8 @@ subroutine carma_register
write(LUNOPRT,*) ' carma_maxretries = ', carma_maxretries
write(LUNOPRT,*) ' carma_vf_const = ', carma_vf_const
write(LUNOPRT,*) ' cldfrc_incloud = ', CLDFRC_INCLOUD
- write(LUNOPRT,*) ' carma_reftfile = ', trim(carma_reftfile)
write(LUNOPRT,*) ' carma_rad_feedback = ', carma_rad_feedback
+ write(LUNOPRT,*) ' carma_sulfnuc_method = ', carma_sulfnuc_method
write(LUNOPRT,*) ''
endif
@@ -309,6 +324,8 @@ subroutine carma_register
! assumptions made in the CAM energy checking and microphysics code.
call CARMA_Initialize(carma, &
rc, &
+ sulfnucl_method = carma_sulfnuc_method, &
+ do_coremasscheck = carma_do_coremasscheck, &
do_clearsky = carma_do_clearsky, &
do_cnst_rlh = .true., &
do_coag = carma_do_coag, &
@@ -338,7 +355,6 @@ subroutine carma_register
tstick = carma_tstick)
if (rc < 0) call endrun('carma_register::CARMA_Initialize failed.')
-
! The elements and gases from CARMA need to be added as constituents in
! CAM (if they don't already exist). For the elements, each radius bin
! needs to be its own constiuent in CAM.
@@ -362,16 +378,14 @@ subroutine carma_register
! For prognostic groups, all of the bins need to be represented as actual CAM
! constituents. Diagnostic groups are determined from state information that
! is already present in CAM, and thus their bins only exist in CARMA.
- if (cnsttype == I_CNSTTYPE_PROGNOSTIC) then
-
- do ibin = 1, NBIN
+ do ibin = 1, NBIN
+ write(btndname(igroup, ibin), '(A, I2.2)') trim(grp_short), ibin
+ if (cnsttype == I_CNSTTYPE_PROGNOSTIC) then
! Bins past maxbin are treated as diagnostic even if the group
! is prognostic and thus are not advected in the paerent model.
if (ibin <= maxbin) then
- write(btndname(igroup, ibin), '(A, I2.2)') trim(grp_short), ibin
-
write(c_name, '(A, I2.2)') trim(shortname), ibin
write(c_longname, '(A, e11.4, A)') trim(name) // ', ', r(ibin)*1.e4_r8, ' um'
@@ -381,8 +395,8 @@ subroutine carma_register
call cnst_add(c_name, WTMOL_AIR, cpair, 0._r8, icnst4elem(ielem, ibin), &
longname=c_longname, mixtype=carma_mixtype, is_convtran1=is_convtran1(igroup))
end if
- end do
- end if
+ end if
+ end do
end do
! Find the constituent for the gas or add it if not found.
@@ -508,16 +522,14 @@ end function carma_implements_cnst
!!
!! @author Chuck Bardeen
!! @version May 2009
- subroutine carma_init
+ subroutine carma_init(pbuf2d)
use cam_history, only: addfld, add_default, horiz_only
- use ioFileMod, only : getfil
use wrap_nf
use time_manager, only: is_first_step
use phys_control, only: phys_getopts
- implicit none
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
- integer :: iz ! vertical index
integer :: ielem ! element index
integer :: ibin ! bin index
integer :: igas ! gas index
@@ -529,15 +541,10 @@ subroutine carma_init
integer :: maxbin ! last prognostic bin
logical :: is_cloud ! is the group a cloud?
logical :: do_drydep ! is dry deposition enabled?
+ integer :: ncore ! number of core elements in the group
- integer :: ier
- integer :: ncid, dimid_lev, vid_T
- logical :: lexist
- character(len=256) :: locfn
- integer :: nlev
- integer :: LUNOPRT ! logical unit number for output
- logical :: do_print ! do print output?
logical :: history_carma
+ logical :: history_carma_srf_flx
1 format(a6,4x,a11,4x,a11,4x,a11)
2 format(i6,4x,3(1pe11.3,4x))
@@ -546,6 +553,7 @@ subroutine carma_init
rc = 0
call phys_getopts(history_carma_out=history_carma)
+ history_carma_srf_flx = .false.
! Set names of constituent sources and declare them as history variables; howver,
! only prognostic variables have.
@@ -589,9 +597,18 @@ subroutine carma_init
call addfld(trim(etndname(ielem, ibin))//'SW', horiz_only, 'A', 'kg/m2/s', &
trim(cnst_name(icnst)) // ' wet deposition flux at surface')
+ if (history_carma_srf_flx) then
+ call add_default(trim(etndname(ielem, ibin))//'EM', 1, ' ')
+ call add_default(trim(etndname(ielem, ibin))//'SF', 1, ' ')
+ call add_default(trim(etndname(ielem, ibin))//'SW', 1, ' ')
+ end if
+
if (do_drydep) then
- call addfld(trim(etndname(ielem, ibin))//'DD', horiz_only, 'A', 'kg/m2/s ', &
- trim(cnst_name(icnst)) // ' dry deposition')
+ call addfld(trim(etndname(ielem, ibin))//'DD', horiz_only, 'A', 'kg/m2/s ', &
+ trim(cnst_name(icnst)) // ' dry deposition')
+ if (history_carma_srf_flx) then
+ call add_default(trim(etndname(ielem, ibin))//'DD', 1, ' ')
+ end if
end if
if (carma_do_pheat) then
@@ -604,7 +621,7 @@ subroutine carma_init
end do
do igroup = 1, NGROUP
- call CARMAGROUP_Get(carma, igroup, rc, shortname=sname, is_cloud=is_cloud, do_drydep=do_drydep)
+ call CARMAGROUP_Get(carma, igroup, rc, shortname=sname, is_cloud=is_cloud, do_drydep=do_drydep, ncore=ncore)
if (rc < 0) call endrun('carma_init::CARMAGROUP_GetGroup failed.')
! Gridbox average
@@ -623,6 +640,7 @@ subroutine carma_init
call addfld(trim(sname)//'PA', (/ 'lev' /), 'A', 'cm2', trim(sname) // ' projected area')
call addfld(trim(sname)//'AR', (/ 'lev' /), 'A', ' ', trim(sname) // ' area ratio')
call addfld(trim(sname)//'VM', (/ 'lev' /), 'A', 'm/s', trim(sname) // ' fall velocity')
+ call addfld(trim(sname)//'VR', (/ 'lev' /), 'A', 'kg/kg', trim(sname) // ' volatile mass mixing ratio')
if (history_carma) then
call add_default(trim(sname)//'ND', 1, ' ')
@@ -636,6 +654,7 @@ subroutine carma_init
call add_default(trim(sname)//'PA', 1, ' ')
call add_default(trim(sname)//'AR', 1, ' ')
call add_default(trim(sname)//'VM', 1, ' ')
+ call add_default(trim(sname)//'VR', 1, ' ')
if (carma_do_grow) then
call add_default(trim(sname)//'JN', 1, ' ')
@@ -644,12 +663,39 @@ subroutine carma_init
! Per bin stats ..
if (do_drydep) then
- do ibin = 1, NBIN
- call addfld(trim(btndname(igroup, ibin))//'VD', horiz_only, 'A', 'm/s', &
- trim(btndname(igroup, ibin))//' dry deposition velocity')
- end do
+ do ibin = 1, NBIN
+ call addfld(trim(btndname(igroup, ibin))//'VD', horiz_only, 'A', 'm/s', &
+ trim(btndname(igroup, ibin)) // ' dry deposition velocity')
+ end do
end if
+ do ibin = 1, NBIN
+ call addfld(trim(btndname(igroup, ibin))//'ND', (/ 'lev' /), 'A', '#/cm3', &
+ trim(btndname(igroup, ibin)) // ' number density')
+ call addfld(trim(btndname(igroup, ibin))//'WR', (/ 'lev' /), 'A', 'um', &
+ trim(btndname(igroup, ibin)) // ' wet radius')
+ call addfld(trim(btndname(igroup, ibin))//'RO', (/ 'lev' /), 'A', 'g/cm3', &
+ trim(btndname(igroup, ibin)) // ' wet particle density')
+ call addfld(trim(btndname(igroup, ibin))//'VR', (/ 'lev' /), 'A', 'um', &
+ trim(btndname(igroup, ibin)) // ' volatile mixing ratio')
+
+
+ if ((carma_ndebugpkgs > 0) .and. (ncore > 0)) then
+ call addfld(trim(btndname(igroup, ibin))//'LCFM', horiz_only, 'A', 'kg/m2', trim(btndname(igroup, ibin)) // ' CARMA local mass fixer fail mass ')
+ call addfld(trim(btndname(igroup, ibin))//'LCFP', horiz_only, 'A', 'probability', trim(btndname(igroup, ibin)) // ' CARMA mass local fail PDF')
+ call addfld(trim(btndname(igroup, ibin))//'LCR', (/ 'lev' /), 'A', 'kg/kg', trim(btndname(igroup, ibin)) // ' CARMA local mass fix MMR')
+ call addfld(trim(btndname(igroup, ibin))//'LCP', (/ 'lev' /), 'A', 'probability', trim(btndname(igroup, ibin)) // ' CARMA local fix PDF')
+
+ if (carma_diags_file > 0) then
+ call add_default(trim(btndname(igroup, ibin))//'LCFM', carma_diags_file, ' ')
+ call add_default(trim(btndname(igroup, ibin))//'LCFP', carma_diags_file, ' ')
+ call add_default(trim(btndname(igroup, ibin))//'LCR', carma_diags_file, ' ')
+ call add_default(trim(btndname(igroup, ibin))//'LCP', carma_diags_file, ' ')
+ end if
+ end if
+
+ end do
+
end do
do igas = 1, NGAS
@@ -708,105 +754,20 @@ subroutine carma_init
if (carma%f_igash2o /= 0) call carma_getH2O(carma_h2o_ref)
if (carma%f_igash2So4 /= 0) call carma_getH2SO4(carma_h2so4_ref)
end if
-
- if (masterproc) then
- call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT)
- if (rc < 0) call endrun('carma_init::CARMA_Get failed.')
-
- if (do_print) write(LUNOPRT,*) ""
- if (do_print) write(LUNOPRT,*) "CARMA initializing to fixed reference state."
- if (do_print) write(LUNOPRT,*) ""
-
- ! For temperature, get the average temperature from reference temperature file
- ! if it exists or from the initial condition file if the reference temperature file
- ! doesn't exist.
- !
- ! NOTE: The reference temperature file will only be created for an inital run. It
- ! must already exist for a restart run.
-
- ! Does reference temperature file already exist?
- call getfil(carma_reftfile, locfn, iflag=1)
-
- inquire(file=locfn, exist=lexist)
-
- ! Read the reference temperature from the file.
- if (lexist) then
-
- ! Open the netcdf file.
- call wrap_open(trim(locfn), NF90_NOWRITE, ncid)
-
- ! Inquire about dimensions
- call wrap_inq_dimid(ncid, 'lev', dimid_lev)
- call wrap_inq_dimlen(ncid, dimid_lev, nlev)
-
- ! Does the number of levels match?
- if (nlev /= pver) then
- call endrun("carma_init::ERROR - Incompatible number of levels &
- &in the CARMA reference temperature file ... " // trim(locfn))
- end if
-
- ! Get variable ID for reference temperature
- call wrap_inq_varid(ncid, 'T', vid_T)
-
- ! Read in the temperature data.
- call wrap_get_var_realx(ncid, vid_T, carma_T_ref)
-
- if (carma%f_igash2o /= 0) then
- ! Get variable ID for reference temperature
- call wrap_inq_varid(ncid, 'Q', vid_T)
-
- ! Read in the temperature data.
- call wrap_get_var_realx(ncid, vid_T, carma_h2o_ref)
- end if
-
- if (carma%f_igash2so4 /= 0) then
- ! Get variable ID for reference temperature
- call wrap_inq_varid(ncid, 'H2SO4', vid_T)
-
- ! Read in the temperature data.
- call wrap_get_var_realx(ncid, vid_T, carma_h2so4_ref)
- end if
-
- ! Close the file
- call wrap_close(ncid)
-
- ! Is this an initial or restart run?
- else if (is_first_step()) then
-
- if (do_print) write(LUNOPRT,*) ""
- if (do_print) write(LUNOPRT,*) 'Creating CARMA reference temperature file ... ', trim(locfn)
-
- ! Save the average into a file to be used for restarts.
- call CARMA_CreateRefTFile(carma, locfn, pref_mid(:) / 100._r8, &
- carma_t_ref(:), rc, refh2o=carma_h2o_ref(:), refh2so4=carma_h2so4_ref(:))
- else
-
- ! The file must already exist for a restart run.
- call endrun("carma_init::ERROR - Can't find the CARMA reference temperature file ... " // trim(carma_reftfile))
-
- end if
-
- ! Write out the values that are being used.
- if (do_print) write(LUNOPRT,*) ""
- if (do_print) write(LUNOPRT,1) "Level","Int P (Pa)","Mid P (Pa)","Mid T (K)"
-
- do iz = 1, pver
- if (do_print) write(LUNOPRT,2) iz, pref_edge(iz), pref_mid(iz), carma_t_ref(iz)
- end do
- if (do_print) write(LUNOPRT,2) iz, pref_edge(iz), 0.0_r8, 0.0_r8
- if (do_print) write(LUNOPRT,*) ""
- end if
-
-#ifdef SPMD
-
- ! Communicate the settings to the other MPI tasks.
- call mpi_bcast(carma_t_ref, pver, MPI_REAL8, 0, mpicom, ier)
-#endif
end if
+ if (is_first_step()) then
+ ! initialize physics buffer fields
+ do igas = 1, NGAS
+ call pbuf_set_field(pbuf2d, ipbuf4gas(igas), 0.0_r8)
+ call pbuf_set_field(pbuf2d, ipbuf4sati(igas), 0.0_r8)
+ call pbuf_set_field(pbuf2d, ipbuf4satl(igas), 0.0_r8)
+ end do
+ call pbuf_set_field(pbuf2d, ipbuf4t, 0.0_r8)
+ endif
! Do a model specific initialization.
- call CARMA_InitializeModel(carma, lq_carma, rc)
+ call CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
if (rc < 0) call endrun('carma_init::CARMA_InitializeModel failed.')
return
@@ -846,9 +807,9 @@ subroutine carma_final
glob_nretry / glob_nstep
else
if (do_print) write(LUNOPRT,2) glob_max_nsubstep, &
- 0., &
+ 0._r8, &
glob_max_nretry, &
- 0.
+ 0._r8
end if
end if
end if
@@ -902,7 +863,7 @@ end subroutine carma_timestep_init
!! @version May-2009
subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rliq, prec_str, snow_str, &
prec_sed, snow_sed, ustar, obklen)
- use time_manager, only: get_nstep, get_step_size, is_first_step
+ use time_manager, only: get_nstep, is_first_step
use camsrfexch, only: cam_in_t, cam_out_t
use planck, only: planckIntensity
@@ -968,9 +929,12 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
real(r8) :: ar(pver) ! Area Ratio
real(r8) :: vm(pver) ! Massweighted fall velocity (cm2)
real(r8) :: jn(pver) ! nucleation (cm-3)
+ real(r8) :: totalmmr(pver) ! total particle mmr (kg/kg)
real(r8) :: numberDensity(pver) ! number density (cm-3)
real(r8) :: nucleationRate(pver) ! nucleation rate (cm-3 s-1)
real(r8) :: extinctionCoefficient(pver) ! extinction coefficient (cm2)
+ real(r8) :: r_wet(pver) ! wet radius (um)
+ real(r8) :: rhop_wet(pver) ! wet particle density (g/cm3)
real(r8) :: dd ! dry deposition (kg/m2)
real(r8) :: vd ! dry deposition velocity (cm/s)
real(r8) :: vf(pverp) ! fall velocity (cm/s)
@@ -986,7 +950,6 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
real(r8), pointer, dimension(:,:) :: tnd_qsnow ! external tendency on snow mass (kg/kg/s)
real(r8), pointer, dimension(:,:) :: tnd_nsnow ! external tendency on snow number(#/kg/s)
real(r8), pointer, dimension(:,:) :: re_ice ! ice effective radius (m)
- integer :: lchnk ! chunk identifier
integer :: iz
real(r8) :: cldfrc(pver) ! cloud fraction [fraction]
real(r8) :: rhcrit(pver) ! relative humidity for onset of liquid clouds [fraction]
@@ -1010,7 +973,6 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
logical :: is_ice ! is the group ice?
logical :: grp_do_drydep ! is dry depostion enabled for group?
logical :: do_drydep ! is dry depostion enabled?
- logical :: do_fixedinit ! do initialization from reference atm?
logical :: do_detrain ! do convective detrainment?
integer :: iwvl
real(r8), parameter :: zzocen = 0.0001_r8 ! Ocean aerodynamic roughness length [m]
@@ -1048,8 +1010,6 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
call cnst_get_ind('Q', icnst_q)
! Get pointers into pbuf ...
- lchnk = state_loc%lchnk
-
call pbuf_get_field(pbuf, ipbuf4t, t_ptr)
! If doing particle heating, then get pointers to the spectral flux data provided
@@ -1080,11 +1040,10 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
! If initializing CARMASTATE from a reference state, do it before entering the main
! loop.
!
- call CARMA_Get(carma, rc, do_fixedinit=do_fixedinit, do_drydep=do_drydep)
+ call CARMA_Get(carma, rc, do_drydep=do_drydep)
if (rc < 0) call endrun('carma_timestep_tend::CARMA_Get failed.')
- if (do_fixedinit) then
-
+ if (carma_do_fixedinit) then
call CARMASTATE_CreateFromReference(cstate, &
carma_ptr, &
time, &
@@ -1101,7 +1060,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
rc, &
qh2o=carma_h2o_ref, &
qh2so4=carma_h2so4_ref)
- if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_CreateFromReference failed.')
+ if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_CreateFromReference failed.')
end if
@@ -1227,7 +1186,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
end do
- call CARMA_DiagnoseBins(carma, cstate, state_loc, pbuf, icol, dt, rc, rliq=rliq, prec_str=prec_str, snow_str=snow_str)
+ call CARMAMODEL_DiagnoseBins(carma, cstate, state_loc, pbuf, icol, dt, rc, rliq=rliq, prec_str=prec_str, snow_str=snow_str)
if (rc < 0) call endrun('carma_timestep_tend::CARMA_DiagnoseBins failed.')
@@ -1237,7 +1196,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
if (rc < 0) call endrun('CARMA_Detrain::CARMA_Get failed.')
if (do_detrain) then
- call CARMA_Detrain(carma, cstate, cam_in, dlf, state_loc, icol, dt, rc, rliq=rliq, prec_str=prec_str, &
+ call CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state_loc, icol, dt, rc, rliq=rliq, prec_str=prec_str, &
snow_str=snow_str, tnd_qsnow=tnd_qsnow, tnd_nsnow=tnd_nsnow)
if (rc < 0) call endrun('carma_timestep_tend::CARMA_Detrain failed.')
end if
@@ -1312,11 +1271,11 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
! NOTE: To work around an XL Fortran compiler bug, the optional arguments can only
! be passed when defined.
if (present(rliq)) then
- call CARMA_DiagnoseBulk(carma, cstate, cam_out, state_loc, pbuf, ptend, icol, dt, rc, &
+ call CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state_loc, pbuf, ptend, icol, dt, rc, &
rliq=rliq, prec_str=prec_str, snow_str=snow_str, prec_sed=prec_sed, &
snow_sed=snow_sed, tnd_qsnow=tnd_qsnow, tnd_nsnow=tnd_nsnow, re_ice=re_ice)
else
- call CARMA_DiagnoseBulk(carma, cstate, cam_out, state_loc, pbuf, ptend, icol, dt, rc)
+ call CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state_loc, pbuf, ptend, icol, dt, rc)
end if
if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_DiagnoseBulk failed.')
@@ -1351,7 +1310,8 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
do ibin = 1, NBIN
call CARMASTATE_GetBin(cstate, ielem, ibin, newstate(:), rc, &
- numberDensity=numberDensity, nucleationRate=nucleationRate, surface=dd, vd=vd, vf=vf, dtpart=dtpart)
+ numberDensity=numberDensity, nucleationRate=nucleationRate, r_wet=r_wet, &
+ rhop_wet=rhop_wet, sedimentationflux=dd, vd=vd, vf=vf, dtpart=dtpart, totalmmr=totalmmr)
if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_GetBin failed.')
! For prognostic groups, set the tendency from the corresponding constituents.
@@ -1367,7 +1327,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
ptend%q(icol, :, icnst) = (newstate(:) - state_loc%q(icol, :, icnst)) / dt
if (grp_do_drydep) then
- sbdiags(icol, ibin, ielem, SBDIAGS_DD) = dd / dt
+ sbdiags(icol, ibin, ielem, SBDIAGS_DD) = dd
sbdiags(icol, ibin, ielem, SBDIAGS_VD) = - vd / 100._r8
end if
end if
@@ -1382,7 +1342,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
re3(:) = re3(:) + numberDensity(:) * ((r(ibin)*rrat(ibin))**3)
ad(:) = ad(:) + numberDensity(:) * 4.0_r8 * PI * (r(ibin)**2) * 1.0e8_r8
md(:) = md(:) + numberDensity(:) * rmass(ibin)
- mr(:) = mr(:) + newstate(:)
+ mr(:) = mr(:) + totalmmr(:)
pa(:) = pa(:) + numberDensity(:) * PI * ((r(ibin) * rrat(ibin))**2) * arat(ibin)
vm(:) = vm(:) + numberDensity(:) * rmass(ibin) * vf(2:) / 100._f
@@ -1397,6 +1357,9 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
od(:) = od(:) + numberDensity(:) * extinctionCoefficient(:) * dz(:) * 100._r8
end if
+ bndiags(icol,:,ibin,ielem,BNDIAGS_VR) = bndiags(icol,:,ibin,ielem,BNDIAGS_VR) + totalmmr(:)
+ gpdiags(icol, :, igroup, GPDIAGS_VR) = gpdiags(icol, :, igroup, GPDIAGS_VR) + totalmmr(:)
+
! Particle temperatures from particle heating.
if (carma_do_pheat) then
bndiags(icol, :, ibin, ielem, BNDIAGS_TP) = dtpart(:)
@@ -1405,6 +1368,12 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
if (nucleationRate(1) /= CAM_FILL) then
jn(:) = jn(:) + nucleationRate(:)
end if
+
+ ! Output nd and wet radius for each bin.
+ r_wet = r_wet * 1e4_r8 ! cm to um
+ bndiags(icol,:,ibin,ielem,BNDIAGS_WETR) = r_wet(:)
+ bndiags(icol,:,ibin,ielem,BNDIAGS_ND) = numberDensity(:)
+ bndiags(icol,:,ibin,ielem,BNDIAGS_RO) = rhop_wet(:)
end do
! If this is the number element for the group, then write out the
@@ -1454,7 +1423,7 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
call pbuf_get_field(pbuf, ipbuf4satl(igas), satl_ptr)
call CARMASTATE_GetGas(cstate, igas, newstate(:), rc, satice=satice, satliq=satliq, &
- eqice=eqice, eqliq=eqliq, wtpct=wtpct)
+ eqice=eqice, eqliq=eqliq, wtpct=wtpct)
if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_GetGas failed.')
icnst = icnst4gas(igas)
@@ -1492,7 +1461,9 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_Get failed.')
spdiags(icol, :, SPDIAGS_NSTEP) = zsubsteps(:)
- spdiags(icol, :, SPDIAGS_LNSTEP) = log(zsubsteps(:))
+ where (zsubsteps/=0.0_r8)
+ spdiags(icol, :, SPDIAGS_LNSTEP) = log(zsubsteps(:))
+ end where
end if
end do
@@ -1517,14 +1488,35 @@ subroutine carma_timestep_tend(state, cam_in, cam_out, ptend, dt, pbuf, dlf, rli
call CARMASTATE_Destroy(cstate, rc)
if (rc < 0) call endrun('carma_timestep_tend::CARMASTATE_Destroy failed.')
-
! Output diagnostic fields.
- call carma_output_diagnostics(state_loc, ptend, gpdiags, sbdiags, gsdiags, spdiags, bndiags)
+ call carma_output_diagnostics(state_loc, ptend, pbuf, cam_in, gpdiags, sbdiags, gsdiags, spdiags, bndiags)
end subroutine carma_timestep_tend
+ !! Get the index for the constituents array for the specified bin
+ !! of the specified element.
+ !!
+ !! @author Yunqian Zhu, Francis Vitt
+ !! @version September-2022
+ subroutine carma_getcnstforbin(ielem, ibin, icnst)
+ implicit none
+
+ integer, intent(in) :: ielem, ibin
+ integer, intent(out) :: icnst
+
+ icnst = icnst4elem(ielem,ibin)
+ return
+ end subroutine carma_getcnstforbin
+
+ !! Collect CARMA substep statistics from all MPI tasks.
+ !!
+ !! @author Chuck Bardeen
+ !! @version May-2009
subroutine carma_accumulate_stats()
+#if ( defined SPMD )
+ use mpishorthand
+#endif
implicit none
integer :: istat
@@ -1600,9 +1592,9 @@ subroutine carma_accumulate_stats()
step_nretry / step_nstep
else
if (do_print) write(LUNOPRT,1) step_max_nsubstep, &
- 0., &
+ 0._r8, &
step_max_nretry, &
- 0.
+ 0._r8
end if
end if
end if
@@ -1665,7 +1657,7 @@ subroutine carma_init_cnst(name, latvals, lonvals, mask, q)
end where
end do
- call CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ call CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
if (rc < 0) call endrun('carma_init_cnst::CARMA_InitializeParticle failed.')
end if
end if
@@ -1679,19 +1671,21 @@ subroutine carma_init_cnst(name, latvals, lonvals, mask, q)
return
end subroutine carma_init_cnst
-
!! Outputs tracer tendencies and diagnositc fields to the history files.
!! All the columns in the chunk should be output at the same time.
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spdiags, bndiags)
+ subroutine carma_output_diagnostics(state, ptend, pbuf, cam_in, gpdiags, sbdiags, gsdiags, spdiags, bndiags)
use cam_history, only: outfld
+ use camsrfexch, only: cam_in_t
implicit none
type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(in), dimension(pcols, pver, NGROUP, NGPDIAGS) :: gpdiags !! CARMA group diagnostic output
real(r8), intent(in), dimension(pcols, NBIN, NELEM, NSBDIAGS) :: sbdiags !! CARMA surface bin diagnostic output
real(r8), intent(in), dimension(pcols, pver, NGAS, NGSDIAGS) :: gsdiags !! CARMA gas diagnostic output
@@ -1706,7 +1700,6 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd
integer :: ienconc ! element index for group's concentration element
integer :: icnst ! constituent index
integer :: lchnk ! chunk identifier
- integer :: ncol ! number of columns
integer :: rc ! CARMA return code
character(len=8) :: sname ! short (CAM) name
integer :: cnsttype ! constituent type
@@ -1714,12 +1707,13 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd
logical :: is_cloud ! is the group a cloud?
logical :: do_drydep ! is dry deposition enabled?
+ character(len=*), parameter :: subname = 'carma_output_diagnostics'
+
! Initialize the return code.
rc = 0
! Check each column int the chunk.
lchnk = state%lchnk
- ncol = state%ncol
! Output step diagnostics.
if (carma_do_substep) then
@@ -1732,10 +1726,10 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd
do ibin = 1, NBIN
call CARMAELEMENT_Get(carma, ielem, rc, igroup=igroup)
- if (rc < 0) call endrun('carma_timestep_tend::CARMAELEMENT_Get failed.')
+ if (rc < 0) call endrun(subname//'::CARMAELEMENT_Get failed.')
call CARMAGROUP_Get(carma, igroup, rc, cnsttype=cnsttype, maxbin=maxbin, do_drydep=do_drydep)
- if (rc < 0) call endrun('carma_timestep_tend::CARMAGROUP_Get failed.')
+ if (rc < 0) call endrun(subname//'::CARMAGROUP_Get failed.')
if (cnsttype == I_CNSTTYPE_PROGNOSTIC) then
@@ -1766,7 +1760,7 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd
! Output the particle diagnostics.
do igroup = 1, NGROUP
call CARMAGROUP_Get(carma, igroup, rc, shortname=sname, is_cloud=is_cloud, do_drydep=do_drydep, ienconc=ienconc)
- if (rc < 0) call endrun('carma_output_diagnostics::CARMAGROUP_Get failed.')
+ if (rc < 0) call endrun(subname//'::CARMAGROUP_Get failed.')
! Gridbox average
call outfld(trim(sname)//'ND', gpdiags(:, :, igroup, GPDIAGS_ND), pcols, lchnk)
@@ -1781,12 +1775,20 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd
call outfld(trim(sname)//'PA', gpdiags(:, :, igroup, GPDIAGS_PA), pcols, lchnk)
call outfld(trim(sname)//'AR', gpdiags(:, :, igroup, GPDIAGS_AR), pcols, lchnk)
call outfld(trim(sname)//'VM', gpdiags(:, :, igroup, GPDIAGS_VM), pcols, lchnk)
+ call outfld(trim(sname)//'VR', gpdiags(:, :, igroup, GPDIAGS_VR), pcols, lchnk)
if (do_drydep) then
do ibin = 1, NBIN
call outfld(trim(btndname(igroup, ibin))//'VD', sbdiags(:, ibin, ienconc, SBDIAGS_VD), pcols, lchnk)
end do
end if
+
+ do ibin = 1,NBIN
+ call outfld(trim(btndname(igroup, ibin))//'ND',bndiags(:, :, ibin, ienconc, BNDIAGS_ND), pcols, lchnk)
+ call outfld(trim(btndname(igroup, ibin))//'WR',bndiags(:, :, ibin, ienconc, BNDIAGS_WETR), pcols, lchnk)
+ call outfld(trim(btndname(igroup, ibin))//'RO',bndiags(:, :, ibin, ienconc, BNDIAGS_RO), pcols, lchnk)
+ call outfld(trim(btndname(igroup, ibin))//'VR',bndiags(:, :, ibin, ienconc, BNDIAGS_VR), pcols, lchnk)
+ end do
end do
! Output the gas tendencies.
@@ -1808,19 +1810,21 @@ subroutine carma_output_diagnostics(state, ptend, gpdiags, sbdiags, gsdiags, spd
call outfld('CRTT', ptend%s(:, :) / cpair, pcols, lchnk)
end if
+ ! Allow models to output their own diagnostics
+ call CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+
return
end subroutine carma_output_diagnostics
-
!! Calculate the emissions for CARMA aerosols. This is taken from
!! the routine aerosol_emis_intr in aerosol_intr.F90 and dust_emis_intr in
!! dust_intr.F90 by Phil Rasch.
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine carma_emission_tend (state, ptend, cam_in, dt)
- use cam_history, only: outfld
- use camsrfexch, only: cam_in_t
+ subroutine carma_emission_tend (state, ptend, cam_in, dt, pbuf)
+ use cam_history, only: outfld
+ use camsrfexch, only: cam_in_t
implicit none
@@ -1828,6 +1832,7 @@ subroutine carma_emission_tend (state, ptend, cam_in, dt)
type(physics_ptend), intent(inout) :: ptend !! physics state tendencies
type(cam_in_t), intent(inout) :: cam_in !! surface inputs
real(r8), intent(in) :: dt !! time step (s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer :: lchnk ! chunk identifier
integer :: ncol ! number of columns in chunk
@@ -1873,7 +1878,7 @@ subroutine carma_emission_tend (state, ptend, cam_in, dt)
icnst = icnst4elem(ielem, ibin)
- call CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ call CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
if (rc < 0) call endrun('carma_emission_tend::CARMA_EmitParticle failed.')
! Add any surface flux here.
@@ -1908,7 +1913,6 @@ end subroutine carma_emission_tend
subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out)
use cam_history, only: outfld
use phys_control, only: cam_physpkg_is
- use phys_grid, only: get_lat_all_p, get_lon_all_p, get_rlat_all_p
use wetdep, only: clddiag, wetdepa_v1, wetdepa_v2
use camsrfexch, only: cam_out_t
use physconst, only: gravit
@@ -1942,7 +1946,7 @@ subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out)
integer :: ixcldice
real(r8) :: totcond(pcols, pver) ! total condensate
real(r8) :: solfac(pcols, pver) ! solubility factor
- real(r8) :: solfactor
+ real(r8) :: solfac_in ! solubility factor
real(r8) :: scavcoef ! scavenging Coefficient
logical :: do_wetdep
integer :: ncol ! number of columns
@@ -2030,11 +2034,11 @@ subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out)
if (rc < 0) call endrun('carma_wetdep_tend::CARMAELEMENT_Get failed.')
call CARMAGROUP_Get(carma, igroup, rc, cnsttype=cnsttype, do_wetdep=do_wetdep, &
- solfac=solfactor, scavcoef=scavcoef, maxbin=maxbin)
- solfac(:ncol,:) = solfactor
-
+ solfac=solfac_in, scavcoef=scavcoef, maxbin=maxbin)
if (rc < 0) call endrun('carma_wetdep_tend::CARMAGROUP_Get failed.')
+ solfac(:,:) = solfac_in
+
if ((do_wetdep) .and. (cnsttype == I_CNSTTYPE_PROGNOSTIC)) then
do ibin = 1, NBIN
@@ -2099,7 +2103,7 @@ subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out)
iscavt, &
cldv, &
fracis(:, :, icnst), &
- solfactor, &
+ solfac_in, &
ncol, &
z_scavcoef)
else
@@ -2122,7 +2126,7 @@ subroutine carma_wetdep_tend(state, ptend, dt, pbuf, dlf, cam_out)
call outfld(trim(cnst_name(icnst))//'SW', sflx, pcols, lchnk)
! Add this to the surface amount of the constituent
- call CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ call CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
end if
end do
@@ -2138,10 +2142,114 @@ end subroutine carma_wetdep_tend
!! code to include the impact of CARMA particles in the radiative transfer
!! calculation.
!!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole.
+ !!
+ !! The I_OPTICS_MIXED_YU2105 and I_OPTICS_SULFATE_YU2015 optics methods are
+ !! designed to trop_strat models as define in the Yu et al. (2015) paper. The
+ !! other optics types can be applied more generically to a number of different
+ !! aerosol/cloud models.
+ !!
!! NOTE: The format of this file is determined by the needs of the radiative tranfer
!! code, so ideally a routine would exist in that module that could create a file
!! with the proper format. Since that doesn't exist, we do it all here.
subroutine CARMA_CreateOpticsFile(carma, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Local variables
+ integer :: igroup
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+ integer :: opticsType
+
+ ! Assume success.
+ rc = 0
+
+ ! Process each group that is defined in the model.
+ do igroup = 1, NGROUP
+
+ ! Get the necessary group properties.
+ call CARMAGROUP_Get(carma, igroup, rc, do_mie=do_mie, cnsttype=cnsttype, iopticstype=opticsType)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGROUP_Get failed.')
+
+ ! Are we supposed to do the mie calculation for this group?
+ if ((do_mie) .and. (cnsttype == I_CNSTTYPE_PROGNOSTIC)) then
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+
+ ! This is for fixed composition, but the particle may swell in response
+ ! to changes in RH. Only one refractive index specified at the group level.
+ !
+ ! NOTE: This is what was used by the first CARMA models that were radiatively
+ ! active.
+ case (I_OPTICS_FIXED)
+ call CARMA_CreateOpticsFile_Fixed(carma, igroup, rc)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::CreateOpticsFile_Fixed failed.')
+
+ ! This is similar to Yu (2015) in that handles mixed particles treated as
+ ! core shell particles; however the dimensions of the lookup table are the
+ ! the radii and the refractive indicies, so it can be used with various
+ ! aerosol configurations (not just as in the Yu(2015)).
+ case(I_OPTICS_MIXED_CORESHELL)
+ call endrun('carma_CreateOpticsFile mixed_coreshell has not been implemented.')
+
+ ! This is similar to MAM4, in that a volume mixing approach is used to
+ ! mixed both the core and the shell together and thus only one radius and
+ ! one refractive index are needed in the lookup table.
+ case(I_OPTICS_MIXED_VOLUME)
+ call endrun('carma_CreateOpticsFile mixed_volume has not been implemented.')
+
+ ! This is similar to "mixed_volume", except that Maxwell-Garnett mixing
+ ! is used instead of volume mixing.
+ case(I_OPTICS_MIXED_MAXWELL)
+ call endrun('carma_CreateOpticsFile mixed_maxwell has not been implemented.')
+
+ ! This is for a pure sulfate group where the table is based upon weight
+ ! percent; however, unlike sulfate_Yu, the refractive index of the sulfate
+ ! changes with the weight percent of H2SO4.
+ case(I_OPTICS_SULFATE)
+ call CARMA_CreateOpticsFile_Sulfate(carma, igroup, rc)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::CreateOpticsFile_Sulfate failed.')
+
+ ! Other types are not generically useful are are particular to the
+ ! specific model, so thos are handled by model specific code. These
+ ! include:
+ ! I_OPTICS_MIXED_YU2015
+ ! I_OPTICS_MIXED_YU_H2O
+ ! I_OPTICS_SULFATE_YU2015
+ case default
+ call CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ end select
+ end if
+ end do
+
+ return
+ end subroutine CARMA_CreateOpticsFile
+
+
+ !! This routine creates files containing optical properties for each radiatively
+ !! active particle type. These optical properties are used by the RRTMG radiation
+ !! code to include the impact of CARMA particles in the radiative transfer
+ !! calculation.
+ !!
+ !! NOTE: The format of this file is determined by the needs of the radiative tranfer
+ !! code, so ideally a routine would exist in that module that could create a file
+ !! with the proper format. Since that doesn't exist, we do it all here.
+ subroutine CARMA_CreateOpticsFile_Fixed(carma, igroup, rc)
use radconstants, only : nswbands, nlwbands
use wrap_nf
use wetr, only : getwetr
@@ -2149,16 +2257,17 @@ subroutine CARMA_CreateOpticsFile(carma, rc)
implicit none
type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group index
integer, intent(out) :: rc !! return code, negative indicates failure
! Local variables
- integer :: igroup, ibin, iwave, irh
+ integer :: ibin, iwave, irh
integer :: irhswell
integer :: ienconc
real(kind=f) :: rho(NBIN), rhopwet
real(kind=f) :: r(NBIN), rmass(NBIN), rlow(NBIN), rup(NBIN)
real(kind=f) :: wave(NWAVE)
- complex(kind=f) :: refidx(NWAVE)
+ complex(kind=f) :: refidx(NWAVE, NREFIDX)
character(len=CARMA_NAME_LEN) :: name
character(len=CARMA_SHORT_NAME_LEN) :: shortname
logical :: do_mie
@@ -2199,381 +2308,661 @@ subroutine CARMA_CreateOpticsFile(carma, rc)
call CARMA_GET(carma, rc, wave=wave, do_print=do_print, LUNOPRT=LUNOPRT)
if (rc < 0) call endrun('carma_CreateOpticsFile::CARMA_Get failed.')
- ! Process each group that is defined in the model.
- do igroup = 1, NGROUP
+ ! Get the necessary group properties.
+ call CARMAGROUP_Get(carma, igroup, rc, do_mie=do_mie, name=name, shortname=shortname, r=r, &
+ rlow=rlow, rup=rup, rmass=rmass, irhswell=irhswell, &
+ ienconc=ienconc, cnsttype=cnsttype, maxbin=maxbin)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGROUP_Get failed.')
- ! Get the necessary group properties.
- call CARMAGROUP_Get(carma, igroup, rc, do_mie=do_mie, name=name, shortname=shortname, r=r, &
- rlow=rlow, rup=rup, rmass=rmass, refidx=refidx, irhswell=irhswell, &
- ienconc=ienconc, cnsttype=cnsttype, maxbin=maxbin)
- if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGROUP_Get failed.')
+ call CARMAELEMENT_Get(carma, ienconc, rc, rho=rho, refidx=refidx)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAELEMENT_Get failed.')
- ! Are we supposed to do the mie calculation for this group?
- if ((do_mie) .and. (cnsttype == I_CNSTTYPE_PROGNOSTIC)) then
+ ! A file needs to be created for each bin.
+ do ibin = 1, NBIN
- call CARMAELEMENT_Get(carma, ienconc, rc, rho=rho)
- if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAELEMENT_Get failed.')
+ ! Bins past maxbin are treated as diagnostic even if the group
+ ! is prognostic and thus are not advected in the paerent model.
+ if (ibin <= maxbin) then
- ! A file needs to be created for each bin.
- do ibin = 1, NBIN
+ write(c_name, '(A, I2.2)') trim(shortname), ibin
- ! Bins past maxbin are treated as diagnostic even if the group
- ! is prognostic and thus are not advected in the paerent model.
- if (ibin <= maxbin) then
+ ! Construct the path to the file. Each model will have its own subdirectory
+ ! where the optical property files are stored.
+ filepath = trim(carma_model) // '_' // trim(c_name) // '_rrtmg.nc'
- write(c_name, '(A, I2.2)') trim(shortname), ibin
+ if (do_print) write(LUNOPRT,*) 'Creating CARMA optics file ... ', trim(filepath)
- ! Construct the path to the file. Each model will have its own subdirectory
- ! where the optical property files are stored.
- filepath = trim(carma_model) // '_' // trim(c_name) // '_rrtmg.nc'
+ ! Create the file.
+ call wrap_create(filepath, NF90_CLOBBER, fid)
- if (do_print) write(LUNOPRT,*) 'Creating CARMA optics file ... ', trim(filepath)
+ ! For non-hygroscopic, only use 1 RH value.
+ if (irhswell /= 0) then
+ nrh = NMIE_RH
+ else
+ nrh = min(NMIE_RH, 1)
+ end if
- ! Create the file.
- call wrap_create(filepath, NF90_CLOBBER, fid)
+ ! Define the dimensions: rh, lwbands, swbands
+ call wrap_def_dim(fid, 'rh_idx', nrh, rhdim)
+ call wrap_def_dim(fid, 'lw_band', nlwbands, lwdim)
+ call wrap_def_dim(fid, 'sw_band', nswbands, swdim)
- ! For non-hygroscopic, only use 1 RH value.
- if (irhswell /= 0) then
- nrh = NMIE_RH
- else
- nrh = min(NMIE_RH, 1)
- end if
+ write(LUNOPRT,*) "Defined rh_idx, lw_band, and sw_band dims."
- ! Define the dimensions: rh, lwbands, swbands
- call wrap_def_dim(fid, 'rh_idx', nrh, rhdim)
- call wrap_def_dim(fid, 'lw_band', nlwbands, lwdim)
- call wrap_def_dim(fid, 'sw_band', nswbands, swdim)
+ dimids(1) = rhdim
+ call wrap_def_var(fid, 'rh', NF90_DOUBLE, 1, dimids(1:1), rhvar)
- write(LUNOPRT,*) "Defined rh_idx, lw_band, and sw_band dims."
+ dimids(1) = lwdim
+ call wrap_def_var(fid, 'lw_band', NF90_DOUBLE, 1, dimids(1:1), lwvar)
- dimids(1) = rhdim
- call wrap_def_var(fid, 'rh', NF90_DOUBLE, 1, dimids(1:1), rhvar)
+ dimids(1) = swdim
+ call wrap_def_var(fid, 'sw_band', NF90_DOUBLE, 1, dimids(1:1), swvar)
- dimids(1) = lwdim
- call wrap_def_var(fid, 'lw_band', NF90_DOUBLE, 1, dimids(1:1), lwvar)
+ write(LUNOPRT,*) "Defined rh_idx, lw_band, and sw_band vars."
- dimids(1) = swdim
- call wrap_def_var(fid, 'sw_band', NF90_DOUBLE, 1, dimids(1:1), swvar)
+ call wrap_put_att_text(fid, rhvar, 'units', 'fraction')
+ call wrap_put_att_text(fid, lwvar, 'units', 'm')
+ call wrap_put_att_text(fid, swvar, 'units', 'm')
- write(LUNOPRT,*) "Defined rh_idx, lw_band, and sw_band vars."
+ call wrap_put_att_text(fid, rhvar, 'long_name', 'relative humidity')
+ call wrap_put_att_text(fid, lwvar, 'long_name', 'longwave bands')
+ call wrap_put_att_text(fid, swvar, 'long_name', 'shortwave bands')
- call wrap_put_att_text(fid, rhvar, 'units', 'fraction')
- call wrap_put_att_text(fid, lwvar, 'units', 'm')
- call wrap_put_att_text(fid, swvar, 'units', 'm')
+ ! Define the variables: abs_lw, ext_sw, ssa_sw, asm_sw
+ dimids(1) = rhdim
+ dimids(2) = lwdim
+ call wrap_def_var(fid, 'abs_lw', NF90_DOUBLE, 2, dimids, abs_lw_var)
- call wrap_put_att_text(fid, rhvar, 'long_name', 'relative humidity')
- call wrap_put_att_text(fid, lwvar, 'long_name', 'longwave bands')
- call wrap_put_att_text(fid, swvar, 'long_name', 'shortwave bands')
+ write(LUNOPRT,*) "Defined abs_lw."
- ! Define the variables: abs_lw, ext_sw, ssa_sw, asm_sw
- dimids(1) = rhdim
- dimids(2) = lwdim
- call wrap_def_var(fid, 'abs_lw', NF90_DOUBLE, 2, dimids, abs_lw_var)
+ call wrap_put_att_text(fid, abs_lw_var, 'units', 'meter^2 kilogram^-1')
- write(LUNOPRT,*) "Defined abs_lw."
+ dimids(1) = rhdim
+ dimids(2) = swdim
+ call wrap_def_var(fid, 'ext_sw', NF90_DOUBLE, 2, dimids, ext_sw_var)
+ call wrap_def_var(fid, 'ssa_sw', NF90_DOUBLE, 2, dimids, ssa_sw_var)
+ call wrap_def_var(fid, 'asm_sw', NF90_DOUBLE, 2, dimids, asm_sw_var)
- call wrap_put_att_text(fid, abs_lw_var, 'units', 'meter^2 kilogram^-1')
+ write(LUNOPRT,*) "Defined ext_sw, ssa_sw, and asm_sw."
- dimids(1) = rhdim
- dimids(2) = swdim
- call wrap_def_var(fid, 'ext_sw', NF90_DOUBLE, 2, dimids, ext_sw_var)
- call wrap_def_var(fid, 'ssa_sw', NF90_DOUBLE, 2, dimids, ssa_sw_var)
- call wrap_def_var(fid, 'asm_sw', NF90_DOUBLE, 2, dimids, asm_sw_var)
+ call wrap_put_att_text(fid, ssa_sw_var, 'units', 'fraction')
+ call wrap_put_att_text(fid, ext_sw_var, 'units', 'meter^2 kilogram^-1')
+ call wrap_put_att_text(fid, asm_sw_var, 'units', '-')
- write(LUNOPRT,*) "Defined ext_sw, ssa_sw, and asm_sw."
+ ! Define the variables for the refractive indicies.
+ dimids(1) = swdim
+ call wrap_def_var(fid, 'refindex_real_aer_sw', NF90_DOUBLE, 1, dimids(1:1), sw_r_refidx_var)
+ call wrap_def_var(fid, 'refindex_im_aer_sw', NF90_DOUBLE, 1, dimids(1:1), sw_i_refidx_var)
- call wrap_put_att_text(fid, ssa_sw_var, 'units', 'fraction')
- call wrap_put_att_text(fid, ext_sw_var, 'units', 'meter^2 kilogram^-1')
- call wrap_put_att_text(fid, asm_sw_var, 'units', '-')
+ write(LUNOPRT,*) "Defined lw refindex."
- ! Define the variables for the refractive indicies.
- dimids(1) = swdim
- call wrap_def_var(fid, 'refindex_real_aer_sw', NF90_DOUBLE, 1, dimids(1:1), sw_r_refidx_var)
- call wrap_def_var(fid, 'refindex_im_aer_sw', NF90_DOUBLE, 1, dimids(1:1), sw_i_refidx_var)
+ dimids(1) = lwdim
+ call wrap_def_var(fid, 'refindex_real_aer_lw', NF90_DOUBLE, 1, dimids(1:1), lw_r_refidx_var)
+ call wrap_def_var(fid, 'refindex_im_aer_lw', NF90_DOUBLE, 1, dimids(1:1), lw_i_refidx_var)
- write(LUNOPRT,*) "Defined lw refindex."
+ write(LUNOPRT,*) "Defined sw refindex."
- dimids(1) = lwdim
- call wrap_def_var(fid, 'refindex_real_aer_lw', NF90_DOUBLE, 1, dimids(1:1), lw_r_refidx_var)
- call wrap_def_var(fid, 'refindex_im_aer_lw', NF90_DOUBLE, 1, dimids(1:1), lw_i_refidx_var)
+ call wrap_put_att_text(fid, sw_r_refidx_var, 'units', '-')
+ call wrap_put_att_text(fid, sw_i_refidx_var, 'units', '-')
+ call wrap_put_att_text(fid, lw_r_refidx_var, 'units', '-')
+ call wrap_put_att_text(fid, lw_i_refidx_var, 'units', '-')
- write(LUNOPRT,*) "Defined sw refindex."
+ call wrap_put_att_text(fid, sw_r_refidx_var, 'long_name', 'real refractive index of aerosol - shortwave')
+ call wrap_put_att_text(fid, sw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - shortwave')
+ call wrap_put_att_text(fid, lw_r_refidx_var, 'long_name', 'real refractive index of aerosol - longwave')
+ call wrap_put_att_text(fid, lw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - longwave')
- call wrap_put_att_text(fid, sw_r_refidx_var, 'units', '-')
- call wrap_put_att_text(fid, sw_i_refidx_var, 'units', '-')
- call wrap_put_att_text(fid, lw_r_refidx_var, 'units', '-')
- call wrap_put_att_text(fid, lw_i_refidx_var, 'units', '-')
- call wrap_put_att_text(fid, sw_r_refidx_var, 'long_name', 'real refractive index of aerosol - shortwave')
- call wrap_put_att_text(fid, sw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - shortwave')
- call wrap_put_att_text(fid, lw_r_refidx_var, 'long_name', 'real refractive index of aerosol - longwave')
- call wrap_put_att_text(fid, lw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - longwave')
+ ! Define fields that define the aerosol properties.
+ call wrap_def_dim(fid, 'opticsmethod_len', 32, omdim)
+ dimids(1) = omdim
+ call wrap_def_var(fid, 'opticsmethod', NF90_CHAR, 1, dimids(1:1), omvar)
+ write(LUNOPRT,*) "Defined omdim."
- ! Define fields that define the aerosol properties.
- call wrap_def_dim(fid, 'opticsmethod_len', 32, omdim)
- dimids(1) = omdim
- call wrap_def_var(fid, 'opticsmethod', NF90_CHAR, 1, dimids(1:1), omvar)
+ call wrap_def_dim(fid, 'namelength', 20, andim)
+ dimids(1) = andim
+ call wrap_def_var(fid, 'aername', NF90_CHAR, 1, dimids(1:1), anvar)
- write(LUNOPRT,*) "Defined omdim."
+ write(LUNOPRT,*) "Defined aername."
- call wrap_def_dim(fid, 'namelength', 20, andim)
- dimids(1) = andim
- call wrap_def_var(fid, 'aername', NF90_CHAR, 1, dimids(1:1), anvar)
+ call wrap_def_dim(fid, 'name_len', 32, namedim)
+ dimids(1) = namedim
+ call wrap_def_var(fid, 'name', NF90_CHAR, 1, dimids(1:1), namevar)
- write(LUNOPRT,*) "Defined aername."
+ write(LUNOPRT,*) "Defined name."
- call wrap_def_dim(fid, 'name_len', 32, namedim)
- dimids(1) = namedim
- call wrap_def_var(fid, 'name', NF90_CHAR, 1, dimids(1:1), namevar)
+ call wrap_def_var(fid, 'density', NF90_DOUBLE, 0, dimids(1:0), denvar)
+ call wrap_def_var(fid, 'sigma_logr', NF90_DOUBLE, 0, dimids(1:0), slogvar)
+ call wrap_def_var(fid, 'dryrad', NF90_DOUBLE, 0, dimids(1:0), dryrvar)
+ call wrap_def_var(fid, 'radmin_aer', NF90_DOUBLE, 0, dimids(1:0), rminvar)
+ call wrap_def_var(fid, 'radmax_aer', NF90_DOUBLE, 0, dimids(1:0), rmaxvar)
+ call wrap_def_var(fid, 'hygroscopicity', NF90_DOUBLE, 0, dimids(1:0), hygrovar)
+ call wrap_def_var(fid, 'num_to_mass_ratio', NF90_DOUBLE, 0, dimids(1:0), ntmvar)
- write(LUNOPRT,*) "Defined name."
+ call wrap_put_att_text(fid, denvar, 'units', 'kg m^-3')
+ call wrap_put_att_text(fid, slogvar, 'units', '-')
+ call wrap_put_att_text(fid, dryrvar, 'units', 'm')
+ call wrap_put_att_text(fid, rminvar, 'units', 'm')
+ call wrap_put_att_text(fid, rmaxvar, 'units', 'm')
+ call wrap_put_att_text(fid, hygrovar, 'units', '-')
+ call wrap_put_att_text(fid, ntmvar, 'units', 'kg^-1')
- call wrap_def_var(fid, 'density', NF90_DOUBLE, 0, dimids(1:0), denvar)
- call wrap_def_var(fid, 'sigma_logr', NF90_DOUBLE, 0, dimids(1:0), slogvar)
- call wrap_def_var(fid, 'dryrad', NF90_DOUBLE, 0, dimids(1:0), dryrvar)
- call wrap_def_var(fid, 'radmin_aer', NF90_DOUBLE, 0, dimids(1:0), rminvar)
- call wrap_def_var(fid, 'radmax_aer', NF90_DOUBLE, 0, dimids(1:0), rmaxvar)
- call wrap_def_var(fid, 'hygroscopicity', NF90_DOUBLE, 0, dimids(1:0), hygrovar)
- call wrap_def_var(fid, 'num_to_mass_ratio', NF90_DOUBLE, 0, dimids(1:0), ntmvar)
+ call wrap_put_att_text(fid, denvar, 'long_name', 'aerosol material density')
+ call wrap_put_att_text(fid, slogvar, 'long_name', 'geometric standard deviation of aerosol')
+ call wrap_put_att_text(fid, dryrvar, 'long_name', 'dry number mode radius of aerosol')
+ call wrap_put_att_text(fid, rminvar, 'long_name', 'minimum dry radius of aerosol for bin')
+ call wrap_put_att_text(fid, rmaxvar, 'long_name', 'maximum dry radius of aerosol for bin')
+ call wrap_put_att_text(fid, hygrovar, 'long_name', 'hygroscopicity of aerosol')
+ call wrap_put_att_text(fid, ntmvar, 'long_name', 'ratio of number to mass of aerosol')
- call wrap_put_att_text(fid, denvar, 'units', 'kg m^-3')
- call wrap_put_att_text(fid, slogvar, 'units', '-')
- call wrap_put_att_text(fid, dryrvar, 'units', 'm')
- call wrap_put_att_text(fid, rminvar, 'units', 'm')
- call wrap_put_att_text(fid, rmaxvar, 'units', 'm')
- call wrap_put_att_text(fid, hygrovar, 'units', '-')
- call wrap_put_att_text(fid, ntmvar, 'units', 'kg^-1')
- call wrap_put_att_text(fid, denvar, 'long_name', 'aerosol material density')
- call wrap_put_att_text(fid, slogvar, 'long_name', 'geometric standard deviation of aerosol')
- call wrap_put_att_text(fid, dryrvar, 'long_name', 'dry number mode radius of aerosol')
- call wrap_put_att_text(fid, rminvar, 'long_name', 'minimum dry radius of aerosol for bin')
- call wrap_put_att_text(fid, rmaxvar, 'long_name', 'maximum dry radius of aerosol for bin')
- call wrap_put_att_text(fid, hygrovar, 'long_name', 'hygroscopicity of aerosol')
- call wrap_put_att_text(fid, ntmvar, 'long_name', 'ratio of number to mass of aerosol')
+ write(LUNOPRT,*) "Defined all variables."
+ ! End the defintion phase of the netcdf file.
+ call wrap_enddef(fid)
- write(LUNOPRT,*) "Defined all variables."
+ ! Write out the dimensions.
+ call wrap_put_var_realx(fid, rhvar, mie_rh(:nrh))
+ call wrap_put_var_realx(fid, lwvar, wave(:nlwbands) * 1e-2_f)
+ call wrap_put_var_realx(fid, swvar, wave(nlwbands+1:) * 1e-2_f)
- ! End the defintion phase of the netcdf file.
- call wrap_enddef(fid)
+ ! Write out the refractive indicies.
+ call wrap_put_var_realx(fid, sw_r_refidx_var, real(refidx(nlwbands+1:, 1)))
+ call wrap_put_var_realx(fid, sw_i_refidx_var, aimag(refidx(nlwbands+1:, 1)))
+ call wrap_put_var_realx(fid, lw_r_refidx_var, real(refidx(:nlwbands, 1)))
+ call wrap_put_var_realx(fid, lw_i_refidx_var, aimag(refidx(:nlwbands, 1)))
- ! Write out the dimensions.
- call wrap_put_var_realx(fid, rhvar, mie_rh(:nrh))
- call wrap_put_var_realx(fid, lwvar, wave(:nlwbands) * 1e-2_f)
- call wrap_put_var_realx(fid, swvar, wave(nlwbands+1:) * 1e-2_f)
+ ! Pad the names out with spaces.
+ aer_name = ' '
+ aer_name(1:len(trim(c_name))) = c_name
+
+ start_text(1) = 1
+ count_text(1) = 32
+ call wrap_put_vara_text(fid, namevar, start_text, count_text, (/ aer_name /))
+ count_text(1) = 20
+ call wrap_put_vara_text(fid, anvar, start_text, count_text, (/ aer_name /))
- ! Write out the refractive indicies.
- call wrap_put_var_realx(fid, sw_r_refidx_var, real(refidx(nlwbands+1:)))
- call wrap_put_var_realx(fid, sw_i_refidx_var, aimag(refidx(nlwbands+1:)))
- call wrap_put_var_realx(fid, lw_r_refidx_var, real(refidx(:nlwbands)))
- call wrap_put_var_realx(fid, lw_i_refidx_var, aimag(refidx(:nlwbands)))
+ ! These fields control whether the particle is treated as a CCN. For now,
+ ! set these so that CARMA particles are not considered as CCN by the
+ ! CAM microphysics.
+ if (irhswell /= 0) then
+ count_text(1) = len('hygroscopic ')
+ call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'hygroscopic ' /))
+ else
+ count_text(1) = len('insoluble ')
+ call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'insoluble ' /))
+ end if
+ call wrap_put_var_realx(fid, denvar, (/ rho(ibin) * 1e-3_f / 1e-6_f /))
+ call wrap_put_var_realx(fid, slogvar, (/ 0._f /))
+ call wrap_put_var_realx(fid, dryrvar, (/ r(ibin) * 1e-2_f /))
+ call wrap_put_var_realx(fid, rminvar, (/ rlow(ibin) * 1e-2_f /))
+ call wrap_put_var_realx(fid, rmaxvar, (/ rup(ibin) * 1e-2_f /))
+ call wrap_put_var_realx(fid, hygrovar, (/ 0._f /))
+ call wrap_put_var_realx(fid, ntmvar, (/ 1._f / rmass(ibin) / 1e-3_f /))
- ! Pad the names out with spaces.
- aer_name = ' '
- aer_name(1:len(trim(c_name))) = c_name
+ ! Iterate over a range of relative humidities, since the particle may swell
+ ! with relative humidity which will change its optical properties.
+ do irh = 1, nrh
- start_text(1) = 1
- count_text(1) = 32
- call wrap_put_vara_text(fid, namevar, start_text, count_text, (/ aer_name /))
- count_text(1) = 20
- call wrap_put_vara_text(fid, anvar, start_text, count_text, (/ aer_name /))
+ ! Determine the wet radius.
+ call getwetr(carma, igroup, mie_rh(irh), r(ibin), rwet, rho(ibin), rhopwet, rc)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::wetr failed.')
- ! These fields control whether the particle is treated as a CCN. For now,
- ! set these so that CARMA particles are not considered as CCN by the
- ! CAM microphysics.
- if (irhswell /= 0) then
- count_text(1) = len('hygroscopic ')
- call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'hygroscopic ' /))
- else
- count_text(1) = len('insoluble ')
- call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'insoluble ' /))
- end if
+ ! Calculate at each wavelength.
+ do iwave = 1, NWAVE
- call wrap_put_var_realx(fid, denvar, (/ rho(ibin) * 1e-3_f / 1e-6_f /))
- call wrap_put_var_realx(fid, slogvar, (/ 0._f /))
- call wrap_put_var_realx(fid, dryrvar, (/ r(ibin) * 1e-2_f /))
- call wrap_put_var_realx(fid, rminvar, (/ rlow(ibin) * 1e-2_f /))
- call wrap_put_var_realx(fid, rmaxvar, (/ rup(ibin) * 1e-2_f /))
- call wrap_put_var_realx(fid, hygrovar, (/ 0._f /))
- call wrap_put_var_realx(fid, ntmvar, (/ 1._f / rmass(ibin) / 1e-3_f /))
-
- ! Iterate over a range of relative humidities, since the particle may swell
- ! with relative humidity which will change its optical properties.
- do irh = 1, nrh
-
- ! Determine the wet radius.
- call getwetr(carma, igroup, mie_rh(irh), r(ibin), rwet, rho(ibin), rhopwet, rc)
- if (rc < 0) call endrun('carma_CreateOpticsFile::wetr failed.')
-
- ! Calculate at each wavelength.
- do iwave = 1, NWAVE
-write(carma%f_LUNOPRT,*) "CARMA mie calc: start ", igroup, ibin, iwave, carma%f_wave(iwave), carma%f_group(igroup)%f_nmon(ibin)
-
-
- ! Using Mie code, calculate the optical properties: extinction coefficient,
- ! single scattering albedo and asymmetry factor.
- ! Assume the particle is homogeneous (no core).
- !
- ! NOTE: nmon, df, rmon and falpha are only used for fractal particles.
- call mie(carma, &
- carma%f_group(igroup)%f_imiertn, &
- rwet, &
- carma%f_wave(iwave), &
- carma%f_group(igroup)%f_nmon(ibin), &
- carma%f_group(igroup)%f_df(ibin), &
- carma%f_group(igroup)%f_rmon, &
- carma%f_group(igroup)%f_falpha, &
- carma%f_group(igroup)%f_refidx(iwave), &
- Qext, &
- Qsca, &
- asym, &
- rc)
- if (rc < 0) call endrun('carma_CreateOpticsFile::mie failed.')
-write(carma%f_LUNOPRT,*) "CARMA mie calc: done ", Qext, Qsca, asym
-
-
- ! Calculate the shortwave and longwave properties?
- !
- ! NOTE: miess is in cgs units, but the optics file needs to be in mks
- ! units, so perform the necessary conversions.
- if (iwave <= nlwbands) then
-
- ! Longwave just needs absorption: abs_lw.
- abs_lw(irh, iwave) = (Qext - Qsca) * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f)
- else
-
- ! Shortwave needs extinction, single scattering albedo and asymmetry factor:
- ! ext_sw, ssa_sw and asm_sw.
- ext_sw(irh, iwave - nlwbands) = Qext * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f)
- ssa_sw(irh, iwave - nlwbands) = Qsca / Qext
- asm_sw(irh, iwave - nlwbands) = asym
- end if
- end do
- end do
+ ! Using Mie code, calculate the optical properties: extinction coefficient,
+ ! single scattering albedo and asymmetry factor.
+ ! Assume the particle is homogeneous (no core).
+ !
+ ! NOTE: nmon, df, rmon and falpha are only used for fractal particles.
+ call mie(carma, &
+ carma%f_group(igroup)%f_imiertn, &
+ rwet, &
+ carma%f_wave(iwave), &
+ real(carma%f_group(igroup)%f_nmon(ibin),kind=f), &
+ carma%f_group(igroup)%f_df(ibin), &
+ carma%f_group(igroup)%f_rmon, &
+ carma%f_group(igroup)%f_falpha, &
+ refidx(iwave, 1), &
+ 0.0_f, &
+ refidx(iwave, 1), &
+ Qext, &
+ Qsca, &
+ asym, &
+ rc)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::mie failed.')
+
+ ! Calculate the shortwave and longwave properties?
+ !
+ ! NOTE: miess is in cgs units, but the optics file needs to be in mks
+ ! units, so perform the necessary conversions.
+ if (iwave <= nlwbands) then
- ! Write out the longwave fields.
- ret = nf90_put_var (fid, abs_lw_var, abs_lw(:nrh, :))
- if (ret/=NF90_NOERR) then
- write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', abs_lw_var
- call handle_error (ret)
- end if
+ ! Longwave just needs absorption: abs_lw.
+ abs_lw(irh, iwave) = (Qext - Qsca) * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f)
+ else
- ! Write out the shortwave fields.
- ret = nf90_put_var (fid, ext_sw_var, ext_sw(:nrh, :))
- if (ret/=NF90_NOERR) then
- write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', ext_sw_var
- call handle_error (ret)
- end if
- ret = nf90_put_var (fid, ssa_sw_var, ssa_sw(:nrh, :))
- if (ret/=NF90_NOERR) then
- write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', ssa_sw_var
- call handle_error (ret)
+ ! Shortwave needs extinction, single scattering albedo and asymmetry factor:
+ ! ext_sw, ssa_sw and asm_sw.
+ ext_sw(irh, iwave - nlwbands) = Qext * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f)
+ ssa_sw(irh, iwave - nlwbands) = Qsca / Qext
+ asm_sw(irh, iwave - nlwbands) = asym
end if
- ret = nf90_put_var (fid, asm_sw_var, asm_sw(:nrh, :))
- if (ret/=NF90_NOERR) then
- write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', asm_sw_var
- call handle_error (ret)
- end if
-
- ! Close the file.
- call wrap_close(fid)
- end if
+ end do
end do
+
+ ! Write out the longwave fields.
+ ret = nf90_put_var (fid, abs_lw_var, abs_lw(:nrh, :))
+ if (ret/=NF90_NOERR) then
+ write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', abs_lw_var
+ call handle_error (ret)
+ end if
+
+ ! Write out the shortwave fields.
+ ret = nf90_put_var (fid, ext_sw_var, ext_sw(:nrh, :))
+ if (ret/=NF90_NOERR) then
+ write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', ext_sw_var
+ call handle_error (ret)
+ end if
+ ret = nf90_put_var (fid, ssa_sw_var, ssa_sw(:nrh, :))
+ if (ret/=NF90_NOERR) then
+ write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', ssa_sw_var
+ call handle_error (ret)
+ end if
+ ret = nf90_put_var (fid, asm_sw_var, asm_sw(:nrh, :))
+ if (ret/=NF90_NOERR) then
+ write(iulog,*)'CARMA_CreateOpticsFile: error writing varid =', asm_sw_var
+ call handle_error (ret)
+ end if
+
+ ! Close the file.
+ call wrap_close(fid)
end if
end do
return
- end subroutine CARMA_CreateOpticsFile
+ end subroutine CARMA_CreateOpticsFile_Fixed
- !! This routine creates a file containing a reference temperature profile
- !! for use with fixed initialization.
- subroutine CARMA_CreateRefTFile(carma, filepath, lev, reft, rc, refh2o, refh2so4)
+
+ !! This routine creates files containing optical properties for the pure sulfate group
+ !! following Yu et al. (2015). These optical properties are used by the RRTMG radiation
+ !! code to include the impact of CARMA particles in the radiative transfer
+ !! calculation.
+ subroutine CARMA_CreateOpticsFile_Sulfate(carma, igroup, rc)
+ use radconstants, only : nswbands, nlwbands
use wrap_nf
+ use wetr, only : getwetr
implicit none
- type(carma_type), intent(inout) :: carma !! the carma object
- character(len=*), intent(in) :: filepath !! the file path
- real(kind=f), intent(in) :: lev(pver) !! pressure levels
- real(kind=f), intent(in) :: reft(pver) !! reference temperature
- integer, intent(out) :: rc !! return code, negative indicates failure
- real(kind=f), optional, intent(in) :: refh2o(pver) !! reference water vapor
- real(kind=f), optional, intent(in) :: refh2so4(pver) !! reference sulfuric acid
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group index
+ integer, intent(out) :: rc !! return code, negative indicates failure
! Local variables
+ integer :: ibin, iwave, iwtp
+ integer :: irhswell
+ integer :: imiertn
+ integer :: ienconc
+ real(kind=f) :: rho(NBIN), rhopwet
+ real(kind=f) :: r(NBIN), rmass(NBIN), rlow(NBIN), rup(NBIN)
+ real(kind=f) :: wave(NWAVE)
+ complex(kind=f) :: refidx(NWAVE)
+ complex(kind=f) :: refidxS(NWAVE, NREFIDX)
+ complex(kind=f) :: refidxW(NWAVE)
+ character(len=CARMA_NAME_LEN) :: name
+ character(len=CARMA_SHORT_NAME_LEN) :: shortname
integer :: fid
- integer :: levdim
- integer :: levvar, tvar, h2ovar, h2so4var
+ integer :: rhdim, lwdim, swdim, wtpdim
+ integer :: rhvar, lwvar, swvar, wtp_var
+ integer :: rwetvar
+ integer :: abs_lw_wtp_var, qabs_lw_wtp_var
+ integer :: ext_sw_wtp_var, ssa_sw_wtp_var, asm_sw_wtp_var, qext_sw_wtp_var
+ integer :: omdim, andim, namedim
+ integer :: omvar, anvar, namevar
integer :: dimids(2)
+ integer :: denvar, slogvar, dryrvar, rminvar, rmaxvar, hygrovar, ntmvar
+ real(kind=f) :: abs_lw_wtp(NMIE_WTP, nlwbands)
+ real(kind=f) :: qabs_lw_wtp(NMIE_WTP, nlwbands)
+ real(kind=f) :: ext_sw_wtp(NMIE_WTP, nswbands)
+ real(kind=f) :: qext_sw_wtp(NMIE_WTP, nswbands)
+ real(kind=f) :: ssa_sw_wtp(NMIE_WTP, nswbands)
+ real(kind=f) :: asm_sw_wtp(NMIE_WTP, nswbands)
+ character(len=8) :: c_name ! constituent name
+ character(len=32) :: aer_name ! long enough for both aername and name
+ character(len=255) :: filepath
+ real(kind=f) :: rwet
+ real(kind=f) :: Qext
+ real(kind=f) :: Qsca
+ real(kind=f) :: asym
+ integer :: start_text(2), count_text(2)
+ integer :: sw_r_refidx_var, sw_i_refidx_var, lw_r_refidx_var, lw_i_refidx_var
+ integer :: cnsttype ! constituent type
+ integer :: maxbin ! last prognostic bin
+ integer :: LUNOPRT ! logical unit number for output
+ logical :: do_print ! do print output?
+ integer :: ret
+ real(kind=f) :: volwater
+ real(kind=f) :: volsulfate
+ real(kind=f) :: volshell
+ integer :: igash2o
! Assume success.
rc = 0
- ! Create the file.
- call wrap_create(filepath, NF90_CLOBBER, fid)
+ ! Get the wavelength structure.
+ call CARMA_GET(carma, rc, wave=wave, do_print=do_print, LUNOPRT=LUNOPRT, igash2o=igash2o)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::CARMA_Get failed.')
+ ! Get the necessary group properties.
+ call CARMAGROUP_Get(carma, igroup, rc, name=name, shortname=shortname, r=r, &
+ rlow=rlow, rup=rup, rmass=rmass, irhswell=irhswell, &
+ ienconc=ienconc, cnsttype=cnsttype, maxbin=maxbin, imiertn=imiertn)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGROUP_Get failed.')
- ! Define the dimensions: lev
- call wrap_def_dim(fid, 'lev', pver, levdim)
+ ! Get the necessary element properties.
+ call CARMAELEMENT_Get(carma, ienconc, rc, rho=rho, refidx=refidxS)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAELEMENT_Get failed.')
- dimids(1) = levdim
- call wrap_def_var(fid, 'lev', NF90_DOUBLE, 1, dimids(1:1), levvar)
+ ! Get the refractive index for water.
+ call CARMAGAS_Get(carma, igash2o, rc, refidx=refidxW)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::CARMAGAS_Get failed.')
- call wrap_put_att_text(fid, levvar, 'units', 'level')
- call wrap_put_att_text(fid, levvar, 'long_name', 'hybrid level at midpoints (1000*(A+B))')
- call wrap_put_att_text(fid, levvar, 'positive', 'down')
- call wrap_put_att_text(fid, levvar, 'standard_name', 'atmosphere_hybrid_sigma_pressure_coordinate')
- call wrap_put_att_text(fid, levvar, 'formula_terms', 'a: hyam b: hybm p0: P0 ps: PS')
+ ! A file needs to be created for each bin.
+ do ibin = 1, NBIN
- ! Define the variables: T
- call wrap_def_var(fid, 'T', NF90_DOUBLE, 1, dimids(1:1), tvar)
+ ! Bins past maxbin are treated as diagnostic even if the group
+ ! is prognostic and thus are not advected in the paerent model.
+ if (ibin <= maxbin) then
- call wrap_put_att_text(fid, tvar, 'units', 'K')
- call wrap_put_att_text(fid, tvar, 'long_name', 'Temperature')
+ write(c_name, '(A, I2.2)') trim(shortname), ibin
- if ((carma%f_igash2o /= 0) .and. present(refh2o)) then
- call wrap_def_var(fid, 'Q', NF90_DOUBLE, 1, dimids(1:1), h2ovar)
+ ! Construct the path to the file. Each model will have its own subdirectory
+ ! where the optical property files are stored.
+ filepath = trim(carma_model) // '_' // trim(c_name) // '_rrtmg.nc'
+
+ if (do_print) write(LUNOPRT,*) 'Creating CARMA optics file ... ', trim(filepath)
- call wrap_put_att_text(fid, h2ovar, 'units', 'kg/kg')
- call wrap_put_att_text(fid, h2ovar, 'long_name', 'Specific Humidity')
- end if
+ ! Create the file.
+ call wrap_create(filepath, NF90_CLOBBER, fid)
+
+ ! Define the dimensions: rh, lwbands, swbands
+ call wrap_def_dim(fid, 'rh_idx', NMIE_RH, rhdim)
+ call wrap_def_dim(fid, 'lw_band', nlwbands, lwdim)
+ call wrap_def_dim(fid, 'sw_band', nswbands, swdim)
+
+ call wrap_def_dim(fid, 'wgtpct', NMIE_WTP, wtpdim)
+
+ dimids(1) = rhdim
+ call wrap_def_var(fid, 'rh', NF90_DOUBLE, 1, dimids(1), rhvar)
+ call wrap_def_var(fid, 'rwet',NF90_DOUBLE, 1, dimids(1), rwetvar)
+
+ dimids(1) = lwdim
+ call wrap_def_var(fid, 'lw_band', NF90_DOUBLE, 1, dimids(1), lwvar)
+
+ dimids(1) = swdim
+ call wrap_def_var(fid, 'sw_band', NF90_DOUBLE, 1, dimids(1), swvar)
+
+ dimids(1) = wtpdim
+ call wrap_def_var(fid, 'wgtpct', NF90_DOUBLE, 1, dimids(1), wtp_var)
+
+ call wrap_put_att_text(fid, rhvar, 'units', 'fraction')
+ call wrap_put_att_text(fid, rwetvar, 'units', 'cm')
+ call wrap_put_att_text(fid, lwvar, 'units', 'm')
+ call wrap_put_att_text(fid, swvar, 'units', 'm')
+
+ call wrap_put_att_text(fid, wtp_var,'units', 'unitless')
+ call wrap_put_att_text(fid, wtp_var,'long_name', 'weight percent')
+
+ call wrap_put_att_text(fid, rhvar, 'long_name', 'relative humidity')
+ call wrap_put_att_text(fid, rwetvar, 'long_name', 'wet radius')
+ call wrap_put_att_text(fid, lwvar, 'long_name', 'longwave bands')
+ call wrap_put_att_text(fid, swvar, 'long_name', 'shortwave bands')
+
+ ! Define the variables: abs_lw, ext_sw, ssa_sw, asm_sw
+ ! Define 2-dimension (:nrh,:nswbands) LW optics properties: abs_lw, qabs_lw
+ dimids(1) = wtpdim
+ dimids(2) = lwdim
+ call wrap_def_var(fid, 'abs_lw_wtp', NF90_DOUBLE, 2, dimids(1:2), abs_lw_wtp_var)
+ call wrap_def_var(fid, 'qabs_lw_wtp',NF90_DOUBLE, 2, dimids(1:2), qabs_lw_wtp_var)
+
+ call wrap_put_att_text(fid, abs_lw_wtp_var, 'units', 'meter^2 kilogram^-1')
+ call wrap_put_att_text(fid, qabs_lw_wtp_var,'units', '-')
+
+ ! Define 2-dimension (:nrh,:nswbands) optics properties: ext_sw, qext_sw, ssa_sw, asm_sw
+ dimids(1) = wtpdim
+ dimids(2) = swdim
+ call wrap_def_var(fid, 'ext_sw_wtp', NF90_DOUBLE, 2, dimids(1:2), ext_sw_wtp_var)
+ call wrap_def_var(fid, 'qext_sw_wtp',NF90_DOUBLE, 2, dimids(1:2), qext_sw_wtp_var)
+ call wrap_def_var(fid, 'ssa_sw_wtp', NF90_DOUBLE, 2, dimids(1:2), ssa_sw_wtp_var)
+ call wrap_def_var(fid, 'asm_sw_wtp', NF90_DOUBLE, 2, dimids(1:2), asm_sw_wtp_var)
+
+ call wrap_put_att_text(fid, ssa_sw_wtp_var, 'units', 'fraction')
+ call wrap_put_att_text(fid, qext_sw_wtp_var,'units', '-')
+ call wrap_put_att_text(fid, ext_sw_wtp_var, 'units', 'meter^2 kilogram^-1')
+ call wrap_put_att_text(fid, asm_sw_wtp_var, 'units', '-')
+
+ ! Define the variables for the refractive indicies.
+ dimids(1) = swdim
+ call wrap_def_var(fid, 'refindex_real_aer_sw', NF90_DOUBLE, 1, dimids(1), sw_r_refidx_var)
+ call wrap_def_var(fid, 'refindex_im_aer_sw', NF90_DOUBLE, 1, dimids(1), sw_i_refidx_var)
+
+ dimids(1) = lwdim
+ call wrap_def_var(fid, 'refindex_real_aer_lw', NF90_DOUBLE, 1, dimids(1), lw_r_refidx_var)
+ call wrap_def_var(fid, 'refindex_im_aer_lw', NF90_DOUBLE, 1, dimids(1), lw_i_refidx_var)
+
+ call wrap_put_att_text(fid, sw_r_refidx_var, 'units', '-')
+ call wrap_put_att_text(fid, sw_i_refidx_var, 'units', '-')
+ call wrap_put_att_text(fid, lw_r_refidx_var, 'units', '-')
+ call wrap_put_att_text(fid, lw_i_refidx_var, 'units', '-')
+
+ call wrap_put_att_text(fid, sw_r_refidx_var, 'long_name', 'real refractive index of aerosol - shortwave')
+ call wrap_put_att_text(fid, sw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - shortwave')
+ call wrap_put_att_text(fid, lw_r_refidx_var, 'long_name', 'real refractive index of aerosol - longwave')
+ call wrap_put_att_text(fid, lw_i_refidx_var, 'long_name', 'imaginary refractive index of aerosol - longwave')
+
+
+ ! Define fields that define the aerosol properties.
+ call wrap_def_dim(fid, 'opticsmethod_len', 32, omdim)
+ dimids(1) = omdim
+ call wrap_def_var(fid, 'opticsmethod', NF90_CHAR, 1, dimids(1), omvar)
+
+ call wrap_def_dim(fid, 'namelength', 20, andim)
+ dimids(1) = andim
+ call wrap_def_var(fid, 'aername', NF90_CHAR, 1, dimids(1), anvar)
+
+ call wrap_def_dim(fid, 'name_len', 32, namedim)
+ dimids(1) = namedim
+ call wrap_def_var(fid, 'name', NF90_CHAR, 1, dimids, namevar)
+
+ call wrap_def_var(fid, 'density', NF90_DOUBLE, 0, dimids(1), denvar)
+ call wrap_def_var(fid, 'sigma_logr', NF90_DOUBLE, 0, dimids(1), slogvar)
+ call wrap_def_var(fid, 'dryrad', NF90_DOUBLE, 0, dimids(1), dryrvar)
+ call wrap_def_var(fid, 'radmin_aer', NF90_DOUBLE, 0, dimids(1), rminvar)
+ call wrap_def_var(fid, 'radmax_aer', NF90_DOUBLE, 0, dimids(1), rmaxvar)
+ call wrap_def_var(fid, 'hygroscopicity', NF90_DOUBLE, 0, dimids(1), hygrovar)
+ call wrap_def_var(fid, 'num_to_mass_ratio', NF90_DOUBLE, 0, dimids(1), ntmvar)
+
+ call wrap_put_att_text(fid, denvar, 'units', 'kg m^-3')
+ call wrap_put_att_text(fid, slogvar, 'units', '-')
+ call wrap_put_att_text(fid, dryrvar, 'units', 'm')
+ call wrap_put_att_text(fid, rminvar, 'units', 'm')
+ call wrap_put_att_text(fid, rmaxvar, 'units', 'm')
+ call wrap_put_att_text(fid, hygrovar, 'units', '-')
+ call wrap_put_att_text(fid, ntmvar, 'units', 'kg^-1')
+
+ call wrap_put_att_text(fid, denvar, 'long_name', 'aerosol material density')
+ call wrap_put_att_text(fid, slogvar, 'long_name', 'geometric standard deviation of aerosol')
+ call wrap_put_att_text(fid, dryrvar, 'long_name', 'dry number mode radius of aerosol')
+ call wrap_put_att_text(fid, rminvar, 'long_name', 'minimum dry radius of aerosol for bin')
+ call wrap_put_att_text(fid, rmaxvar, 'long_name', 'maximum dry radius of aerosol for bin')
+ call wrap_put_att_text(fid, hygrovar, 'long_name', 'hygroscopicity of aerosol')
+ call wrap_put_att_text(fid, ntmvar, 'long_name', 'ratio of number to mass of aerosol')
+
+ ! End the defintion phase of the netcdf file.
+ call wrap_enddef(fid)
+
+ ! Write out the dimensions.
+ call wrap_put_var_realx(fid, rhvar, mie_rh(:))
+ call wrap_put_var_realx(fid, lwvar, wave(:nlwbands) * 1e-2_f)
+ call wrap_put_var_realx(fid, swvar, wave(nlwbands+1:) * 1e-2_f)
+
+ call wrap_put_var_realx(fid, wtp_var, mie_wtp(:)*100._f)
+
+ ! Write out the refractive indicies.
+ call wrap_put_var_realx(fid, sw_r_refidx_var, real(refidxS(nlwbands+1:, 1)))
+ call wrap_put_var_realx(fid, sw_i_refidx_var, aimag(refidxS(nlwbands+1:, 1)))
+ call wrap_put_var_realx(fid, lw_r_refidx_var, real(refidxS(:nlwbands, 1)))
+ call wrap_put_var_realx(fid, lw_i_refidx_var, aimag(refidxS(:nlwbands, 1)))
+
+ ! Pad the names out with spaces.
+ aer_name = ' '
+ aer_name(1:len(trim(c_name))) = c_name
+
+ start_text(1) = 1
+ count_text(1) = 32
+ call wrap_put_vara_text(fid, namevar, start_text, count_text, (/ aer_name /))
+ count_text(1) = 20
+ call wrap_put_vara_text(fid, anvar, start_text, count_text, (/ aer_name /))
+
+ count_text(1) = len('hygroscopic_wtp ')
+ call wrap_put_vara_text(fid, omvar, start_text, count_text, (/ 'hygroscopic_wtp ' /))
+
+ call wrap_put_var_realx(fid, denvar, (/ rho(ibin) * 1e-3_f / 1e-6_f /))
+ call wrap_put_var_realx(fid, slogvar, (/ 0._f /))
+ call wrap_put_var_realx(fid, dryrvar, (/ r(ibin) * 1e-2_f /))
+ call wrap_put_var_realx(fid, rminvar, (/ rlow(ibin) * 1e-2_f /))
+ call wrap_put_var_realx(fid, rmaxvar, (/ rup(ibin) * 1e-2_f /))
+ call wrap_put_var_realx(fid, hygrovar, (/ 0.6_f /))
+ call wrap_put_var_realx(fid, ntmvar, (/ 1._f / rmass(ibin) / 1e-3_f /))
+
+ ! For now, ext_sw(:nrh, :nswbands) and ext_sw_coreshell(:nrh, :nswbands, :ncoreshellratio) both are calculated
+ ! Since other aerosols in CAM may use ext_sw rather than ext_sw_coreshell
+ ! Modified by Pengfei Yu
+ ! April.1, 2012
+
+ ! calculate qext and ext for pure sulfate dependent on weight percent
+ ! ideally qext is based on (wgt,temp,wave), however Beyer et al. (1996) Figure 5
+ ! shows sulfate density is roughly 0.006 g/cm3/k, I negelet temp dimension, assuming temp = 270 K
+ ! In code, sulfate density is precisely calculated to determine wet raidus
+ do iwtp = 1, NMIE_WTP
+
+ ! NOTE: Weight percent is normal a result of the getwetr calculation. To build the
+ ! table based upon weight percent, we need to pass in the desired value and a
+ ! reference temperature. In that case, the RH is ignored.
+ call getwetr(carma, igroup, mie_rh(1), r(ibin), rwet, rho(ibin), rhopwet, rc, wgtpct=mie_wtp(iwtp)*100._f, temp=270._f)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::wetr failed.')
+
+ ! This is not in Yu (2015), but rather than using the refractive
+ ! index of H2SO4 for the shell, do a volume mix of water and H2SO4
+ ! for the refractive index of the shell.
+ volwater = rwet**3._f - r(ibin)**3._f
+ volsulfate = r(ibin)**3._f
+ volshell = volwater + volsulfate
+ if (volshell > 0._f) then
+ refidx(:) = (volwater / volshell) * refidxW(:) + (volsulfate / volshell) * refidxS(:, 1)
+ else
+ refidx(:) = refidxS(:, 1)
+ end if
- if ((carma%f_igash2so4 /= 0) .and. present(refh2so4)) then
- call wrap_def_var(fid, 'H2SO4', NF90_DOUBLE, 1, dimids(1:1), h2so4var)
+ ! Calculate at each wavelength.
+ do iwave = 1, NWAVE
- call wrap_put_att_text(fid, h2so4var, 'units', 'kg/kg')
- call wrap_put_att_text(fid, h2so4var, 'long_name', 'H2SO4')
- end if
+ ! Using Mie code, calculate the optical properties: extinction coefficient,
+ ! single scattering albedo and asymmetry factor.
+ ! Assume the particle is homogeneous (no core).
+ !
+ ! NOTE: The refractive index for sulfate changes with RH/weight percent, which
+ ! is not reflected in this code.
+ call mie(carma, &
+ imiertn, &
+ rwet, &
+ wave(iwave), &
+ 0._f, &
+ 3.0_f, &
+ 0.0_f, &
+ 1.0_f, &
+ refidx(iwave), &
+ 0.0_f, &
+ refidx(iwave), &
+ Qext, &
+ Qsca, &
+ asym, &
+ rc)
+ if (rc < 0) call endrun('carma_CreateOpticsFile::mie failed.')
+
+ ! Calculate the shortwave and longwave properties?
+ !
+ ! NOTE: miess is in cgs units, but the optics file needs to be in mks
+ ! units, so perform the necessary conversions.
+ if (iwave <= nlwbands) then
- ! End the defintion phase of the netcdf file.
- call wrap_enddef(fid)
+ ! Longwave just needs absorption: abs_lw.
+ qabs_lw_wtp(iwtp, iwave) = (Qext - Qsca) ! absorption per particle
+ abs_lw_wtp (iwtp, iwave) = (Qext - Qsca) * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f)
+ else
+ ! Shortwave needs extinction, single scattering albedo and asymmetry factor:
+ ! ext_sw, ssa_sw and asm_sw.
+ qext_sw_wtp(iwtp, iwave - nlwbands) = Qext ! extinction per particle
+ ext_sw_wtp (iwtp, iwave - nlwbands) = Qext * PI * (rwet * 1e-2_f)**2 / (rmass(ibin) * 1e-3_f)
+ ssa_sw_wtp (iwtp, iwave - nlwbands) = Qsca / Qext
+ asm_sw_wtp (iwtp, iwave - nlwbands) = asym
+ end if
+ end do ! iwave
+ end do ! iwtp
+
+ ! Write out the longwave fields.
+ ret = nf90_put_var(fid, abs_lw_wtp_var, abs_lw_wtp (:, :))
+ if (ret /= NF90_NOERR) then
+ write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', fid, abs_lw_wtp_var
+ call handle_error(ret)
+ end if
- ! Write out the dimensions.
- call wrap_put_var_realx(fid, levvar, lev)
+ ret = nf90_put_var(fid, qabs_lw_wtp_var, qabs_lw_wtp(:, :))
+ if (ret /= NF90_NOERR) then
+ write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', qabs_lw_wtp_var
+ call handle_error(ret)
+ end if
- ! Write out the variables.
- call wrap_put_var_realx(fid, tvar, reft)
+ ! Write out the shortwave fields.
+ ret = nf90_put_var(fid, ext_sw_wtp_var, ext_sw_wtp (:, :))
+ if (ret /= NF90_NOERR) then
+ write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', ext_sw_wtp_var
+ call handle_error(ret)
+ end if
- if ((carma%f_igash2o /= 0) .and. present(refh2o)) then
- call wrap_put_var_realx(fid, h2ovar, refh2o(:))
- end if
+ ret = nf90_put_var(fid, qext_sw_wtp_var,qext_sw_wtp(:, :))
+ if (ret /= NF90_NOERR) then
+ write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', qext_sw_wtp_var
+ call handle_error(ret)
+ end if
- if ((carma%f_igash2so4 /= 0) .and. present(refh2so4)) then
- call wrap_put_var_realx(fid, h2so4var, refh2so4(:))
- end if
+ ret = nf90_put_var(fid, ssa_sw_wtp_var, ssa_sw_wtp (:, :))
+ if (ret /= NF90_NOERR) then
+ write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', ssa_sw_wtp_var
+ call handle_error(ret)
+ end if
+
+ ret = nf90_put_var(fid, asm_sw_wtp_var, asm_sw_wtp (:, :))
+ if (ret /= NF90_NOERR) then
+ write(iulog,*)'CARMA_CreateOpticsFile_SulfateYu: error writing varid =', asm_sw_wtp_var
+ call handle_error(ret)
+ end if
- ! Close the file.
- call wrap_close(fid)
+ ! Close the file.
+ call wrap_close(fid)
+ end if
+ end do
return
- end subroutine CARMA_CreateRefTFile
+ end subroutine CARMA_CreateOpticsFile_Sulfate
!! Calculate the aerodynamic resistance for dry deposition.
@@ -2645,4 +3034,87 @@ subroutine CARMA_calcram(ustar, z0, pdel, pmid, tmid, obklen, ram)
return
end subroutine CARMA_calcram
+
+ !---------------------------------------------------------------------------
+ ! define fields for reference profiles in cam restart file
+ !---------------------------------------------------------------------------
+ subroutine CARMA_restart_init( File )
+ use cam_pio_utils, only: cam_pio_def_dim
+ use pio, only: file_desc_t, pio_def_var, pio_double
+
+ ! arguments
+ type(file_desc_t),intent(inout) :: File ! pio File pointer
+
+ ! local variables
+ integer :: levid, ierr
+
+ if (carma_do_fixedinit) then
+ call cam_pio_def_dim(File, 'lev', pver, levid, existOK=.true.)
+ ierr = pio_def_var(File, 'CARMA_REF_T', pio_double, (/ levid /), t_ref_desc)
+ ierr = pio_def_var(File, 'CARMA_REF_H2O', pio_double, (/ levid /), h2o_ref_desc)
+ ierr = pio_def_var(File, 'CARMA_REF_H2SO4', pio_double, (/ levid /), h2so4_ref_desc)
+ endif
+
+ end subroutine CARMA_restart_init
+
+ !---------------------------------------------------------------------------
+ ! write reference profiles to restart file
+ !---------------------------------------------------------------------------
+ subroutine CARMA_restart_write(File)
+ use pio, only: file_desc_t, pio_put_var
+
+ ! arguments
+ type(file_desc_t), intent(inout) :: File
+
+ ! local variables
+ integer ::ierr
+
+ if (carma_do_fixedinit) then
+ ierr = pio_put_var(File, t_ref_desc, carma_t_ref)
+ if (carma%f_igash2o /= 0) then
+ ierr = pio_put_var(File, h2o_ref_desc, carma_h2o_ref)
+ endif
+ if (carma%f_igash2So4 /= 0) then
+ ierr = pio_put_var(File, h2so4_ref_desc, carma_h2so4_ref)
+ endif
+ endif
+
+ end subroutine CARMA_restart_write
+
+ !---------------------------------------------------------------------------
+ ! read reference profiles from restart file
+ !---------------------------------------------------------------------------
+ subroutine CARMA_restart_read(File)
+ use pio, only: file_desc_t, pio_inq_varid, pio_get_var
+
+ ! arguments
+ type(file_desc_t),intent(inout) :: File ! pio File pointer
+
+ ! local variables
+ integer :: ierr, varid
+ character(len=*), parameter :: subname = 'CARMA_restart_read: '
+
+ if (carma_do_fixedinit) then
+ ierr = pio_inq_varid(File, 'CARMA_REF_T', varid)
+ if (varid>0) then
+ ierr = pio_get_var(File, varid, carma_t_ref)
+ else
+ call endrun(subname//'restart file must include CARMA_REF_T')
+ endif
+ ierr = pio_inq_varid(File, 'CARMA_REF_H2O', varid)
+ if (varid>0) then
+ ierr = pio_get_var(File, varid, carma_h2o_ref)
+ else if (carma%f_igash2o /= 0) then
+ call endrun(subname//'restart file must include CARMA_REF_H2O')
+ endif
+ ierr = pio_inq_varid(File, 'CARMA_REF_H2SO4', varid)
+ if (varid>0) then
+ ierr = pio_get_var(File, varid, carma_h2so4_ref)
+ else if (carma%f_igash2So4 /= 0) then
+ call endrun(subname//'restart file must include CARMA_REF_H2SO4')
+ endif
+ endif
+
+ end subroutine CARMA_restart_read
+
end module carma_intr
diff --git a/src/physics/carma/cam/carma_precision_mod.F90 b/src/physics/carma/cam/carma_precision_mod.F90
index db76f798c6..ae22471312 100644
--- a/src/physics/carma/cam/carma_precision_mod.F90
+++ b/src/physics/carma/cam/carma_precision_mod.F90
@@ -35,4 +35,4 @@ module carma_precision_mod
!! Define smallest possible number such that ONE + ALMOST_ZERO > ONE
real(kind=f), parameter :: ALMOST_ZERO = epsilon( ONE )
real(kind=f), parameter :: ALMOST_ONE = ONE - ALMOST_ZERO
-end module
+end module carma_precision_mod
diff --git a/src/physics/carma/models/bc_strat/carma_model_mod.F90 b/src/physics/carma/models/bc_strat/carma_model_mod.F90
index 42dc276a01..e4a933dd67 100644
--- a/src/physics/carma/models/bc_strat/carma_model_mod.F90
+++ b/src/physics/carma/models/bc_strat/carma_model_mod.F90
@@ -417,4 +417,4 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
return
end subroutine CARMA_WetDeposition
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/cirrus/carma_model_mod.F90 b/src/physics/carma/models/cirrus/carma_model_mod.F90
index 446a17cdd8..b751221964 100644
--- a/src/physics/carma/models/cirrus/carma_model_mod.F90
+++ b/src/physics/carma/models/cirrus/carma_model_mod.F90
@@ -315,7 +315,7 @@ subroutine CARMA_DefineModel(carma, rc)
! Read in the tables.
call wrap_inq_varid(fid, 'wavelength', wave_vid)
call wrap_get_var_realx(fid, wave_vid, warren_wave)
- warren_wave = warren_wave * 1e-4 ! um -> cm
+ warren_wave = warren_wave * 1e-4_r8 ! um -> cm
call wrap_inq_varid(fid, 'm_real', real_vid)
call wrap_get_var_realx(fid, real_vid, warren_real)
@@ -1344,7 +1344,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! Now integrate the snow distribution. We know the snow amount, but need an effective radius
! to determine the snow number.
sub_d = 2._f * (r(NBIN) + (dr(NBIN) / 2._f)) * shapeFactor
- sub_dd = (snow_max_d * 1e-4 - sub_d) / NINTS_SNOW
+ sub_dd = (snow_max_d * 1e-4_r8 - sub_d) / NINTS_SNOW
sub_d = sub_d + sub_dd / 2._f
remainder = 0._f
@@ -1361,7 +1361,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! m = aD^2.1
!
! NOTE: This needs to match the density assumption made in the detrained ice bins.
- remainder = remainder + nsnow / lambda * 4.22e-3_f * (sub_d**2.1)
+ remainder = remainder + nsnow / lambda * 4.22e-3_f * (sub_d**2.1_r8)
sub_d = sub_d + sub_dd
end do
@@ -1374,7 +1374,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! Now integrate the snow distribution. We know the snow amount, but need an effective radius
! to determine the snow number.
snow_d = 2._f * ((r(NBIN) + dr(NBIN) / 2._f))
- sub_dd = (snow_max_d * 1e-4 - snow_d) / NINTS_SNOW
+ sub_dd = (snow_max_d * 1e-4_r8 - snow_d) / NINTS_SNOW
sub_d = snow_d + (sub_dd / 2._f)
snow_r3 = 0._f
@@ -2064,4 +2064,4 @@ subroutine CARMA_CheckMassAndEnergy(carma, cstate, madeSnow, name, state, &
return
end subroutine CARMA_CheckMassAndEnergy
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/cirrus/growevapl.F90 b/src/physics/carma/models/cirrus/growevapl.F90
index e1020eb802..c6659bdbb4 100644
--- a/src/physics/carma/models/cirrus/growevapl.F90
+++ b/src/physics/carma/models/cirrus/growevapl.F90
@@ -216,7 +216,7 @@ subroutine growevapl(carma, cstate, iz, rc)
if( x .lt. 1._f )then
growlg(ibin,igroup) = dmdt(ibin)/pc(iz,ibin,iepart) &
- * ( ar(ibin) - 0.5*dela(ibin)*x + &
+ * ( ar(ibin) - 0.5_r8*dela(ibin)*x + &
(x/2._f - x**2/3._f)*a6(ibin) )
else
growlg(ibin,igroup) = dmdt(ibin) / dm(ibin,igroup)
diff --git a/src/physics/carma/models/cirrus_dust/carma_mod.F90 b/src/physics/carma/models/cirrus_dust/carma_mod.F90
index ab89065690..f6ac6945ae 100644
--- a/src/physics/carma/models/cirrus_dust/carma_mod.F90
+++ b/src/physics/carma/models/cirrus_dust/carma_mod.F90
@@ -1475,4 +1475,4 @@ subroutine CARMA_Get(carma, rc, LUNOPRT, NBIN, NELEM, NGAS, NGROUP, NSOLUTE, NWA
return
end subroutine CARMA_Get
-end module
+end module carma_mod
diff --git a/src/physics/carma/models/cirrus_dust/carma_model_mod.F90 b/src/physics/carma/models/cirrus_dust/carma_model_mod.F90
index 036e1ea977..0ff512539e 100644
--- a/src/physics/carma/models/cirrus_dust/carma_model_mod.F90
+++ b/src/physics/carma/models/cirrus_dust/carma_model_mod.F90
@@ -335,7 +335,7 @@ subroutine CARMA_DefineModel(carma, rc)
! Read in the tables.
call wrap_inq_varid(fid, 'wavelength', wave_vid)
call wrap_get_var_realx(fid, wave_vid, warren_wave)
- warren_wave = warren_wave * 1e-4 ! um -> cm
+ warren_wave = warren_wave * 1e-4_r8 ! um -> cm
call wrap_inq_varid(fid, 'm_real', real_vid)
call wrap_get_var_realx(fid, real_vid, warren_real)
@@ -1386,7 +1386,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! Now integrate the snow distribution. We know the snow amount, but need an effective radius
! to determine the snow number.
sub_d = 2._f * (r(NBIN) + (dr(NBIN) / 2._f)) * shapeFactor
- sub_dd = (snow_max_d * 1e-4 - sub_d) / NINTS_SNOW
+ sub_dd = (snow_max_d * 1e-4_r8 - sub_d) / NINTS_SNOW
sub_d = sub_d + sub_dd / 2._f
remainder = 0._f
@@ -1403,7 +1403,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! m = aD^2.1
!
! NOTE: This needs to match the density assumption made in the detrained ice bins.
- remainder = remainder + nsnow / lambda * 4.22e-3_f * (sub_d**2.1)
+ remainder = remainder + nsnow / lambda * 4.22e-3_f * (sub_d**2.1_r8)
sub_d = sub_d + sub_dd
end do
@@ -1416,7 +1416,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! Now integrate the snow distribution. We know the snow amount, but need an effective radius
! to determine the snow number.
snow_d = 2._f * ((r(NBIN) + dr(NBIN) / 2._f))
- sub_dd = (snow_max_d * 1e-4 - snow_d) / NINTS_SNOW
+ sub_dd = (snow_max_d * 1e-4_r8 - snow_d) / NINTS_SNOW
sub_d = snow_d + (sub_dd / 2._f)
snow_r3 = 0._f
@@ -2570,7 +2570,7 @@ subroutine CARMA_SurfaceWind(carma, state, icol, ilat, ilon, ielem, igroup, ibin
* sqrt(1._r8 + .006_r8/rhop(ibin)/GRAV/(r(ibin)*2._r8)**2.5_r8) &
/ sqrt(1.928_r8*(1331._r8*(r(ibin)*2._r8)**1.56_r8 + .38_r8)**.092_r8 - 1._r8)
else
- uth = uthfact*1.e-2_r8* 0.13_r8 * sqrt(rhop(ibin)*GRAV*(.75e-4_r8)*2./rhoa) &
+ uth = uthfact*1.e-2_r8* 0.13_r8 * sqrt(rhop(ibin)*GRAV*(.75e-4_r8)*2._r8/rhoa) &
* sqrt(1._r8 + .006_r8/rhop(ibin)/GRAV/((.75e-4_r8)*2._r8)**2.5_r8) &
/ sqrt(1.928_r8*(1331._r8*((.75e-4_r8)*2._r8)**1.56_r8 + .38_r8)**.092_r8 - 1._r8)
endif
@@ -2703,7 +2703,7 @@ subroutine WeibullWind(u, uth, n, uwb, wbk)
if (present(wbk)) then
k = wbk
else
- k = 0.94*u**0.5_r8 ! follow Grini and Zender, 2004JGR
+ k = 0.94_r8*u**0.5_r8 ! follow Grini and Zender, 2004JGR
! k = 2.5_r8 ! Lansing's estimate
end if
@@ -2718,4 +2718,4 @@ subroutine WeibullWind(u, uth, n, uwb, wbk)
end subroutine WeibullWind
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/cirrus_dust/growevapl.F90 b/src/physics/carma/models/cirrus_dust/growevapl.F90
index e1020eb802..c6659bdbb4 100644
--- a/src/physics/carma/models/cirrus_dust/growevapl.F90
+++ b/src/physics/carma/models/cirrus_dust/growevapl.F90
@@ -216,7 +216,7 @@ subroutine growevapl(carma, cstate, iz, rc)
if( x .lt. 1._f )then
growlg(ibin,igroup) = dmdt(ibin)/pc(iz,ibin,iepart) &
- * ( ar(ibin) - 0.5*dela(ibin)*x + &
+ * ( ar(ibin) - 0.5_r8*dela(ibin)*x + &
(x/2._f - x**2/3._f)*a6(ibin) )
else
growlg(ibin,igroup) = dmdt(ibin) / dm(ibin,igroup)
diff --git a/src/physics/carma/models/dust/carma_model_mod.F90 b/src/physics/carma/models/dust/carma_model_mod.F90
index 22ba9b69d2..09c96b2bf0 100644
--- a/src/physics/carma/models/dust/carma_model_mod.F90
+++ b/src/physics/carma/models/dust/carma_model_mod.F90
@@ -46,14 +46,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 1 !! Number of particle groups
@@ -66,6 +71,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -90,7 +99,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
type(carma_type), intent(inout) :: carma !! the carma object
integer, intent(out) :: rc !! return code, negative indicates failure
@@ -107,7 +116,7 @@ subroutine CARMA_DefineModel(carma, rc)
! Report model specific namelist configuration parameters.
if (masterproc) then
call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT)
- if (rc < 0) call endrun("CARMA_DefineModel: CARMA_Get failed.")
+ if (rc < 0) call endrun("CARMAMODEL_DefineModel: CARMA_Get failed.")
if (do_print) write(LUNOPRT,*) ''
if (do_print) write(LUNOPRT,*) 'CARMA ', trim(carma_model), ' specific settings :'
@@ -122,7 +131,7 @@ subroutine CARMA_DefineModel(carma, rc)
call CARMAGROUP_Create(carma, 1, "dust", rmin, vmrat, I_SPHERE, 1._f, .false., &
rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, &
scavcoef=0.1_f, shortname="CRDUST")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.')
! Define the Elements
@@ -130,7 +139,7 @@ subroutine CARMA_DefineModel(carma, rc)
! NOTE: For CAM, the optional shortname needs to be provided for the group. These names
! should be 6 characters or less and without spaces.
call CARMAELEMENT_Create(carma, 1, 1, "dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="CRDUST")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
! Define the Solutes
@@ -143,7 +152,7 @@ subroutine CARMA_DefineModel(carma, rc)
return
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -153,7 +162,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair
@@ -178,14 +187,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -211,14 +220,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! code to determine the mass in each bin from the CAM state.
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use camsrfexch, only: cam_out_t
@@ -249,7 +258,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
! code to determine the bulk mass from the CARMA state.
return
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
!! Calculates the emissions for CARMA aerosol particles. By default, there is no
@@ -258,7 +267,7 @@ end subroutine CARMA_DiagnoseBulk
!!
!! @author Lin Su, Pengfei Yu, Chuck Bardeen
!! @version Dec-2010
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -276,10 +285,9 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
- integer :: ilat(pcols) ! latitude index
- integer :: ilon(pcols) ! longitude index
integer :: lchnk ! chunk identifier
integer :: ncol ! number of columns in chunk
integer :: icol ! column index
@@ -341,7 +349,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
! Process each column.
do icol = 1,ncol
- call CARMA_SurfaceWind(carma, state, icol, ielem, igroup, idustbin, cam_in, uv10, wwd, uth, rc)
+ call CARMAMODEL_SurfaceWind(carma, state, icol, ielem, igroup, idustbin, cam_in, uv10, wwd, uth, rc)
! Is the wind above the threshold for dust production?
if (uv10 > uth) then
@@ -351,16 +359,15 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
! Scale the clay bins based upon the smallest silt bin.
surfaceFlux(icol) = clay_mf(ibin) * surfaceFlux(icol)
-
end do
! For debug purposes, output the soil erosion factor.
call outfld('CRSLERFC', soil_factor(:ncol, lchnk), ncol, lchnk)
- end if
+ end if
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -368,16 +375,17 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use cam_history, only: addfld, add_default, horiz_only
use constituents, only: pcnst
implicit none
- type(carma_type), intent(in) :: carma !! the carma object
- logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
+ type(carma_type), intent(in) :: carma !! the carma object
+ logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
- integer, intent(out) :: rc !! return code, negative indicates failure
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
+ integer, intent(out) :: rc !! return code, negative indicates failure
! -------- local variables ----------
integer :: ibin ! CARMA bin index
@@ -421,7 +429,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
end do
! Read in the soil factors.
- call CARMA_ReadSoilErosionFactor(carma, rc)
+ call CARMAMODEL_ReadSoilErosionFactor(carma, rc)
if (RC < RC_ERROR) return
! To determine Clay Mass Fraction
@@ -431,7 +439,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
if (RC < RC_ERROR) return
if (shortname .eq. "CRDUST") then
- call CARMA_ClayMassFraction(carma, igroup, rc)
+ call CARMAMODEL_ClayMassFraction(carma, igroup, rc)
end if
end do
@@ -452,7 +460,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
call addfld('CRSLERFC', horiz_only, 'A', 'fraction', 'CARMA soil erosion factor')
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -464,7 +472,7 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use pmgrid, only: plev
@@ -487,15 +495,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
! NOTE: Initialized to 0. by the caller, so nothing needs to be done.
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
!! wet deposition of CARMA aerosols to the aerosols being communicated to the surface.
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -514,7 +562,7 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
rc = RC_OK
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
!! Determines the mass fraction for the clay (submicron) bins based upon
@@ -529,7 +577,7 @@ end subroutine CARMA_WetDeposition
!!
!! @version July-2012
!! @author Lin Su, Pengfei Yu, Chuck Bardeen
- subroutine CARMA_ClayMassFraction(carma, igroup, rc)
+ subroutine CARMAMODEL_ClayMassFraction(carma, igroup, rc)
implicit none
type(carma_type), intent(in) :: carma !! the carma object
@@ -610,7 +658,7 @@ subroutine CARMA_ClayMassFraction(carma, igroup, rc)
clay_mf(ind_low(IABOVE):) = 1._r8
return
- end subroutine CARMA_ClayMassFraction
+ end subroutine CARMAMODEL_ClayMassFraction
!! Calculate the sea surface wind with a Weibull distribution.
@@ -621,7 +669,7 @@ end subroutine CARMA_ClayMassFraction
!!
!! @author Lin Su, Pengfei Yu, Chuck Bardeen
!! @version July-2012
- subroutine CARMA_SurfaceWind(carma, state, icol, ielem, igroup, ibin, cam_in, uv10, wwd, uth, rc)
+ subroutine CARMAMODEL_SurfaceWind(carma, state, icol, ielem, igroup, ibin, cam_in, uv10, wwd, uth, rc)
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
use camsrfexch, only: cam_in_t
@@ -669,7 +717,7 @@ subroutine CARMA_SurfaceWind(carma, state, icol, ielem, igroup, ibin, cam_in, uv
* sqrt(1._r8 + .006_r8/rhop(ibin)/GRAV/(r(ibin)*2._r8)**2.5_r8) &
/ sqrt(1.928_r8*(1331._r8*(r(ibin)*2._r8)**1.56_r8 + .38_r8)**.092_r8 - 1._r8)
else
- uth = uthfact*1.e-2_r8* 0.13_r8 * sqrt(rhop(ibin)*GRAV*(.75e-4_r8)*2./rhoa) &
+ uth = uthfact*1.e-2_r8* 0.13_r8 * sqrt(rhop(ibin)*GRAV*(.75e-4_r8)*2._r8/rhoa) &
* sqrt(1._r8 + .006_r8/rhop(ibin)/GRAV/((.75e-4_r8)*2._r8)**2.5_r8) &
/ sqrt(1.928_r8*(1331._r8*((.75e-4_r8)*2._r8)**1.56_r8 + .38_r8)**.092_r8 - 1._r8)
endif
@@ -681,7 +729,7 @@ subroutine CARMA_SurfaceWind(carma, state, icol, ielem, igroup, ibin, cam_in, uv
call WeibullWind(uv10, uth, 2._r8, wwd)
return
- end subroutine CARMA_SurfaceWind
+ end subroutine CARMAMODEL_SurfaceWind
!! Read in the dust source (soil) erodibility factor from a NETCDF file. In this
@@ -693,7 +741,7 @@ end subroutine CARMA_SurfaceWind
!!
!! @author Pengfei Yu
!! @version July-2012
- subroutine CARMA_ReadSoilErosionFactor(carma, rc)
+ subroutine CARMAMODEL_ReadSoilErosionFactor(carma, rc)
use ppgrid, only: begchunk, endchunk, pcols
use ioFileMod, only: getfil
use wrap_nf
@@ -742,7 +790,7 @@ subroutine CARMA_ReadSoilErosionFactor(carma, rc)
call wrap_inq_varid(fid, 'new_source', idvar)
i = nf90_get_var (fid, idvar, ero_factor)
if (i/=NF90_NOERR) then
- write(iulog,*)'CARMA_ReadSoilErosionFactor: error reading varid =', idvar
+ write(iulog,*)'CARMAMODEL_ReadSoilErosionFactor: error reading varid =', idvar
call handle_error (i)
end if
call wrap_inq_varid(fid, 'plat', idlat)
@@ -775,7 +823,8 @@ subroutine CARMA_ReadSoilErosionFactor(carma, rc)
deallocate(ero_lon)
deallocate(ero_factor)
- end subroutine CARMA_ReadSoilErosionFactor
+ return
+ end subroutine CARMAMODEL_ReadSoilErosionFactor
!! Calculate the nth mean of u using Weibull wind distribution
@@ -804,7 +853,7 @@ subroutine WeibullWind(u, uth, n, uwb, wbk)
if (present(wbk)) then
k = wbk
else
- k = 0.94*u**0.5_r8 ! follow Grini and Zender, 2004JGR
+ k = 0.94_r8*u**0.5_r8 ! follow Grini and Zender, 2004JGR
! k = 2.5_r8 ! Lansing's estimate
end if
@@ -819,4 +868,92 @@ subroutine WeibullWind(u, uth, n, uwb, wbk)
end subroutine WeibullWind
-end module
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
+
+end module carma_model_mod
diff --git a/src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90 b/src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90
index 360ddb9499..efe43af66d 100644
--- a/src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90
+++ b/src/physics/carma/models/meteor_impact/carma_model_flags_mod.F90
@@ -24,16 +24,16 @@ module carma_model_flags_mod
!
! Create a public definition of any new namelist variables that you wish to have,
! and default them to an inital value.
- real(r8), public :: carma_emis_dust = 0._r8 !! Total dust emission for the event (kg)
- real(r8), public :: carma_emis_soot = 0._r8 !! Total soot emission for the event (kg)
- integer, public :: carma_emis_startdate = 1 !! start year and day of year (yyyyddd)
- integer, public :: carma_emis_stopdate = 1 !! stop year and day of year (yyyyddd)
- integer, public :: carma_emis_starttime = 0 !! start time of day (s)
- integer, public :: carma_emis_stoptime = 0 !! stop time of day (s)
- real(r8), public :: carma_emis_minlat = -90. !! minimum latitude
- real(r8), public :: carma_emis_maxlat = 90. !! maximum latitude
- real(r8), public :: carma_emis_minlon = 0. !! minimum longitude
- real(r8), public :: carma_emis_maxlon = 360. !! maximum longitude
+ real(r8), public :: carma_emis_dust = 0._r8 !! Total dust emission for the event (kg)
+ real(r8), public :: carma_emis_soot = 0._r8 !! Total soot emission for the event (kg)
+ integer, public :: carma_emis_startdate = 1 !! start year and day of year (yyyyddd)
+ integer, public :: carma_emis_stopdate = 1 !! stop year and day of year (yyyyddd)
+ integer, public :: carma_emis_starttime = 0 !! start time of day (s)
+ integer, public :: carma_emis_stoptime = 0 !! stop time of day (s)
+ real(r8), public :: carma_emis_minlat = -90._r8 !! minimum latitude
+ real(r8), public :: carma_emis_maxlat = 90._r8 !! maximum latitude
+ real(r8), public :: carma_emis_minlon = 0._r8 !! minimum longitude
+ real(r8), public :: carma_emis_maxlon = 360._r8 !! maximum longitude
logical, public :: carma_fractal_soot = .false. !! fractal Soot
contains
diff --git a/src/physics/carma/models/meteor_impact/carma_model_mod.F90 b/src/physics/carma/models/meteor_impact/carma_model_mod.F90
index f8ebec713d..ecc131f0cf 100755
--- a/src/physics/carma/models/meteor_impact/carma_model_mod.F90
+++ b/src/physics/carma/models/meteor_impact/carma_model_mod.F90
@@ -42,14 +42,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 2 !! Number of particle groups
@@ -65,6 +70,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH) = (/ 0._f, 0.5_f, 0.7_f, 0.8_f, 0.9_f, 0.95_f, 0.98_f, 0.99_f /)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -96,7 +105,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
type(carma_type), intent(inout) :: carma !! the carma object
integer, intent(out) :: rc !! return code, negative indicates failure
@@ -107,7 +116,7 @@ subroutine CARMA_DefineModel(carma, rc)
real(kind=f), parameter :: dust_vmrat = 2.49_f ! dust volume ratio
real(kind=f), parameter :: soot_rmin = 20.e-7_f ! dust minimum radius (cm)
real(kind=f), parameter :: soot_vmrat = 2.49_f ! dust volume ratio
- complex(kind=f) :: refidx(NWAVE) ! refractice indices
+ complex(kind=f) :: refidx(NWAVE,NREFIDX) ! refractice indices
integer :: LUNOPRT ! logical unit number for output
logical :: do_print ! do print output?
@@ -123,13 +132,13 @@ subroutine CARMA_DefineModel(carma, rc)
if (carma_emis_maxlon < 0._f) carma_emis_maxlon = 360._f + carma_emis_maxlon
if (carma_emis_minlat > carma_emis_maxlat) then
- if (do_print) write(LUNOPRT,*) 'CARMA_DefineModel::ERROR - carma_emis_minlat greater than carma_emis_maxlat'
+ if (do_print) write(LUNOPRT,*) 'CARMAMODEL_DefineModel::ERROR - carma_emis_minlat greater than carma_emis_maxlat'
end if
! Report model specific namelist configuration parameters.
if (masterproc) then
call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT)
- if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.")
+ if (rc < 0) call endrun("CARMAMODEL_DefineModel: CARMA_Get failed.")
if (do_print) write(LUNOPRT,*) ''
if (do_print) write(LUNOPRT,*) 'CARMA ', trim(carma_model), ' specific settings :'
@@ -154,19 +163,10 @@ subroutine CARMA_DefineModel(carma, rc)
! defined. If wetdep is defined, then the optional solubility factor
! should also be defined.
- ! Use the same refractive index at all wavelengths. This value is typical of soot and
- ! is recommended by Toon et al. 2012. TBD Wagner et al. 2011 shows variability in the
- ! real part (0.003 (IR) to 0.05 (UV)).
- refidx(:) = (1.53_f, 0.008_f)
-
call CARMAGROUP_Create(carma, I_GRP_DUST, "Dust", dust_rmin, dust_vmrat, I_SPHERE, 1._f, .false., &
rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, &
- scavcoef=0.1_f, shortname="CRDUST", refidx=refidx, do_mie=.true.)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.')
-
- ! Use the same refractive index at all wavelengths. This value is typical of soot and
- ! is recommended by Toon et al. 2012.
- refidx(:) = (1.8_f, 0.67_f)
+ scavcoef=0.1_f, shortname="CRDUST", do_mie=.true.)
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.')
if (carma_fractal_soot) then
RHO_SOOT = 1.8_f
@@ -178,27 +178,37 @@ subroutine CARMA_DefineModel(carma, rc)
call CARMAGROUP_Create(carma, I_GRP_SOOT, "Soot", soot_rmin, soot_vmrat, I_SPHERE, 1._f, .false., &
rc, do_wetdep=.true., do_drydep=.true., solfac=0.1_f, &
- scavcoef=0.1_f, shortname="CRSOOT", refidx=refidx, do_mie=.true., &
+ scavcoef=0.1_f, shortname="CRSOOT", do_mie=.true., &
is_fractal=.true., rmon=soot_rmon, df=soot_df, falpha=soot_falpha, &
imiertn=I_MIERTN_BOTET1997)
else
RHO_SOOT = 1.0_f
call CARMAGROUP_Create(carma, I_GRP_SOOT, "Soot", soot_rmin, soot_vmrat, I_SPHERE, 1._f, .false., &
rc, do_wetdep=.true., do_drydep=.true., solfac=0.1_f, &
- scavcoef=0.1_f, shortname="CRSOOT", refidx=refidx, do_mie=.true.)
+ scavcoef=0.1_f, shortname="CRSOOT", do_mie=.true.)
end if
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.')
! Define the Elements
!
! NOTE: For CAM, the optional shortname needs to be provided for the group. These names
! should be 6 characters or less and without spaces.
- call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="CRDUST")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
- call CARMAELEMENT_Create(carma, I_ELEM_SOOT, I_GRP_SOOT, "Soot", RHO_SOOT, I_INVOLATILE, I_SOOT, rc, shortname="CRSOOT")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ ! Use the same refractive index at all wavelengths. This value is typical of dust and
+ ! is recommended by Toon et al. 2012. TBD Wagner et al. 2011 shows variability in the
+ ! real part (0.003 (IR) to 0.05 (UV)).
+ refidx(:,1) = CMPLX(1.53_f, 0.008_f, kind=f)
+
+ call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="CRDUST", refidx=refidx)
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
+
+ ! Use the same refractive index at all wavelengths. This value is typical of soot and
+ ! is recommended by Toon et al. 2012.
+ refidx(:,1) = CMPLX(1.8_f, 0.67_f, kind=f)
+
+ call CARMAELEMENT_Create(carma, I_ELEM_SOOT, I_GRP_SOOT, "Soot", RHO_SOOT, I_INVOLATILE, I_SOOT, rc, shortname="CRSOOT", refidx=refidx)
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
! Define the Solutes
@@ -209,13 +219,13 @@ subroutine CARMA_DefineModel(carma, rc)
! Define the Processes
call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_DUST, I_GRP_DUST, I_COLLEC_DATA, rc)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.')
call CARMA_AddCoagulation(carma, I_GRP_SOOT, I_GRP_SOOT, I_GRP_SOOT, I_COLLEC_DATA, rc)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.')
return
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -225,7 +235,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair
@@ -250,14 +260,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -283,14 +293,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! code to determine the mass in each bin from the CAM state.
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use camsrfexch, only: cam_out_t
@@ -329,7 +339,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
do ibin = 1, NBIN
call CARMASTATE_GetBin(cstate, ielem, ibin, mmr, rc, sedimentationFlux=sflx)
- if (rc < 0) call endrun('CARMA_DiagnoseBulk::CARMA_GetBin failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DiagnoseBulk::CARMA_GetBin failed.')
cam_out%bcphidry(icol) = cam_out%bcphidry(icol) + max(sflx, 0._r8)
end do
@@ -338,7 +348,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
do ibin = 1, NBIN
call CARMASTATE_GetBin(cstate, ielem, ibin, mmr, rc, sedimentationFlux=sflx)
- if (rc < 0) call endrun('CARMA_DiagnoseBulk::CARMA_GetBin failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DiagnoseBulk::CARMA_GetBin failed.')
if (carma_dustmap(ibin) == 1) then
cam_out%dstdry1(icol) = cam_out%dstdry1(icol) + max(sflx, 0._r8)
@@ -352,7 +362,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
end do
return
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
!! Calculates the emissions for CARMA aerosol particles. By default, there is no
@@ -361,7 +371,7 @@ end subroutine CARMA_DiagnoseBulk
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -382,6 +392,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
real(r8), parameter :: mu_dust_gnd = 1._r8 ! width parameter, dust, ground (km)
@@ -563,7 +574,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
end if
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -574,7 +585,7 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use constituents, only: pcnst
use phys_grid, only: get_rlat_all_p, get_rlon_all_p, get_area_all_p, get_ncols_p
use shr_reprosum_mod, only: shr_reprosum_calc
@@ -586,14 +597,15 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
type(carma_type), intent(in) :: carma !! the carma object
logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer, intent(out) :: rc !! return code, negative indicates failure
! NOTE: The dust distribution has not been specified yet, but it should be different
! from the soot.
- real(kind=f), parameter :: rm_dust = 0.11 ! dust mean radius (um)
- real(kind=f), parameter :: sigma_dust = 1.6 ! dust variance
- real(kind=f), parameter :: rm_soot = 0.11 ! soot mean radius (um)
- real(kind=f), parameter :: sigma_soot = 1.6 ! soot variance
+ real(kind=f), parameter :: rm_dust = 0.11_r8 ! dust mean radius (um)
+ real(kind=f), parameter :: sigma_dust = 1.6_r8 ! dust variance
+ real(kind=f), parameter :: rm_soot = 0.11_r8 ! soot mean radius (um)
+ real(kind=f), parameter :: sigma_soot = 1.6_r8 ! soot variance
integer :: i
real(kind=f) :: r(NBIN)
@@ -735,7 +747,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
end if
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -747,7 +759,7 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
implicit none
@@ -767,15 +779,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
! Add initial condition here.
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
!! wet deposition of CARMA aerosols to the aerosols being communicated to the surface.
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -817,6 +869,121 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
end if
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
+
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ integer :: icol !! column index
+ integer :: ibin !! bin index
+ real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s
+ real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s
+ character(len=16) :: binname !! names bins
+ real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer :: i
+ integer :: icnst !! constituent index
+ integer :: ienconc !! concentration element index
+ integer :: ncore !! number of cores
+ integer :: icorelem(NELEM) !! core element index
+ real(r8) :: mair(pver) !! Mass of air column (kg/m2)
+ real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2)
+ real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2)
+ real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s)
+ real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s)
+ real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2)
+ real(r8) :: so2(pcols) !! SO2 gas (kg/m2)
+ real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2)
+ real(r8) :: bddust(pcols) !! Burden dust (kg/m2)
+ real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2)
+ real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2)
+ real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2)
+ character(len=16) :: shortname
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/meteor_smoke/carma_model_mod.F90 b/src/physics/carma/models/meteor_smoke/carma_model_mod.F90
index 0b6d83aba1..4ec2910f44 100644
--- a/src/physics/carma/models/meteor_smoke/carma_model_mod.F90
+++ b/src/physics/carma/models/meteor_smoke/carma_model_mod.F90
@@ -42,14 +42,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 1 !! Number of particle groups
@@ -62,6 +67,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -102,7 +111,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
type(carma_type), intent(inout) :: carma !! the carma object
integer, intent(out) :: rc !! return code, negative indicates failure
@@ -120,7 +129,7 @@ subroutine CARMA_DefineModel(carma, rc)
! Report model specific namelist configuration parameters.
if (masterproc) then
call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT)
- if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.")
+ if (rc < 0) call endrun("CARMAMODEL_DefineModel: CARMA_Get failed.")
if (do_print) write(LUNOPRT,*) ''
if (do_print) write(LUNOPRT,*) 'CARMA ', trim(carma_model), ' specific settings :'
@@ -139,7 +148,7 @@ subroutine CARMA_DefineModel(carma, rc)
call CARMAGROUP_Create(carma, I_GRP_DUST, "meteor smoke", rmin, vmrat, I_SPHERE, 1._f, .false., &
rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, &
scavcoef=0.1_f, shortname="DUST")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.')
! Define the Elements
@@ -148,7 +157,7 @@ subroutine CARMA_DefineModel(carma, rc)
! should be 6 characters or less and without spaces.
call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "meteor smoke", RHO_METEOR_SMOKE, &
I_INVOLATILE, I_METEOR_SMOKE, rc, shortname="DUST")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
! Define the Solutes
@@ -159,10 +168,10 @@ subroutine CARMA_DefineModel(carma, rc)
! Define the Processes
call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_DUST, I_GRP_DUST, I_COLLEC_DATA, rc)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.')
return
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -172,7 +181,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair
@@ -197,14 +206,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -230,14 +239,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! code to determine the mass in each bin from the CAM state.
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use camsrfexch, only: cam_out_t
@@ -268,7 +277,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
! code to determine the bulk mass from the CARMA state.
return
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
!! Calculates the emissions for CARMA aerosol particles. By default, there is no
@@ -277,7 +286,7 @@ end subroutine CARMA_DiagnoseBulk
!!
!! @author Chuck Bardeen
!! @version Jan-2011
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -296,6 +305,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
integer :: ilat ! latitude index
@@ -435,7 +445,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
end if
end do
- if (abs((state%lat(icol) / DEG2RAD) - 90.0) <= 0.00001_r8) then
+ if (abs((state%lat(icol) / DEG2RAD) - 90.0_r8) <= 0.00001_r8) then
rfScale(icol) = carma_escale_grf(carma_escale_nLats, doy)
end if
@@ -481,7 +491,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
end if
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -489,7 +499,7 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use ioFileMod, only: getfil
use constituents, only: pcnst
use wrap_nf
@@ -499,6 +509,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
type(carma_type), intent(in) :: carma !! the carma object
logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer, intent(out) :: rc !! return code, negative indicates failure
integer :: ilev ! level index
@@ -524,7 +535,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! Add initialization here.
call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT)
- if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.")
+ if (rc < 0) call endrun("CARMAMODEL_InitializeModel: CARMA_Get failed.")
! Initialize the emissions rate table.
if (carma_do_emission) then
@@ -565,7 +576,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
carma_emis_ilev_max = carma_emis_nLevs
do ilev = 1, carma_emis_nLevs
- if (carma_emis_rate(ilev) <= 0.0) then
+ if (carma_emis_rate(ilev) <= 0.0_r8) then
carma_emis_ilev_min = ilev + 1
else
exit
@@ -573,7 +584,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
end do
do ilev = carma_emis_nLevs, 1, -1
- if (carma_emis_rate(ilev) <= 0.0) then
+ if (carma_emis_rate(ilev) <= 0.0_r8) then
carma_emis_ilev_max = ilev - 1
else
exit
@@ -642,7 +653,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! There should be one time for each day of the year, so
! quit if it isn't correct.
if (carma_escale_nTimes .ne. 365) then
- call endrun("CARMA_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.")
+ call endrun("CARMAMODEL_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.")
endif
call wrap_inq_dimid(fid, "ltime", ltime_did)
@@ -665,7 +676,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
call wrap_inq_varid(fid, 'SGRF', grf_vid)
tmp = nf90_get_var (fid, grf_vid, carma_escale_grf)
if (tmp/=NF90_NOERR) then
- write(iulog,*) 'CARMA_InitializeModel: error reading varid =', grf_vid
+ write(iulog,*) 'CARMAMODEL_InitializeModel: error reading varid =', grf_vid
call handle_error (tmp)
end if
@@ -701,7 +712,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
endif
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -713,8 +724,9 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
+ use pmgrid, only: plat, plev, plon
implicit none
@@ -735,15 +747,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
! NOTE: Initialized to 0. by the caller, so nothing needs to be done.
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
!! wet deposition of CARMA aerosols to the aerosols being communicated to the surface.
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -762,6 +814,121 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
rc = RC_OK
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
+
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ integer :: icol !! column index
+ integer :: ibin !! bin index
+ real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s
+ real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s
+ character(len=16) :: binname !! names bins
+ real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer :: i
+ integer :: icnst !! constituent index
+ integer :: ienconc !! concentration element index
+ integer :: ncore !! number of cores
+ integer :: icorelem(NELEM) !! core element index
+ real(r8) :: mair(pver) !! Mass of air column (kg/m2)
+ real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2)
+ real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2)
+ real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s)
+ real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s)
+ real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2)
+ real(r8) :: so2(pcols) !! SO2 gas (kg/m2)
+ real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2)
+ real(r8) :: bddust(pcols) !! Burden dust (kg/m2)
+ real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2)
+ real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2)
+ real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2)
+ character(len=16) :: shortname
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/mixed_sulfate/carma_model_mod.F90 b/src/physics/carma/models/mixed_sulfate/carma_model_mod.F90
index 36ee1be358..5f21fbf4d9 100644
--- a/src/physics/carma/models/mixed_sulfate/carma_model_mod.F90
+++ b/src/physics/carma/models/mixed_sulfate/carma_model_mod.F90
@@ -50,14 +50,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 2 !! Number of particle groups
@@ -70,6 +75,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -121,7 +130,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
use ioFileMod, only: getfil
use wrap_nf
@@ -144,7 +153,7 @@ subroutine CARMA_DefineModel(carma, rc)
rc = RC_OK
call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_Get failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.')
! Report model specific configuration parameters.
if (masterproc) then
@@ -167,7 +176,7 @@ subroutine CARMA_DefineModel(carma, rc)
call CARMAGROUP_Create(carma, I_GRP_DUST, "meteor smoke", rmin, 2.0_f, I_SPHERE, 1._f, .false., &
rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, &
scavcoef=0.1_f, shortname="DUST")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.')
! NOTE: For CAM, the optional do_wetdep and do_drydep flags should be
@@ -180,7 +189,7 @@ subroutine CARMA_DefineModel(carma, rc)
call CARMAGROUP_Create(carma, I_GRP_SULFATE, "sulfate", rmin_sulfate, vmrat_sulfate, I_SPHERE, 1._f, .false., &
rc, irhswell=I_WTPCT_H2SO4, do_wetdep=.true., do_drydep=.true., solfac=1.0_f, &
scavcoef=0.1_f, is_sulfate=.true., shortname="SULF")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.')
! Define the Elements
@@ -189,15 +198,15 @@ subroutine CARMA_DefineModel(carma, rc)
! should be 6 characters or less and without spaces.
call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "meteor smoke", RHO_METEOR_SMOKE, &
I_INVOLATILE, I_METEOR_SMOKE, rc, shortname="DUST")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
call CARMAELEMENT_Create(carma, I_ELEM_SULFATE, I_GRP_SULFATE, "sulfate", RHO_SULFATE, &
I_VOLATILE, I_H2SO4, rc, shortname="SULF")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
call CARMAELEMENT_Create(carma, I_ELEM_SULCORE, I_GRP_SULFATE, "sulfate core", RHO_METEOR_SMOKE, &
I_COREMASS, I_METEOR_SMOKE, rc, shortname="SFCORE")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
! Define the Solutes
!
@@ -208,40 +217,40 @@ subroutine CARMA_DefineModel(carma, rc)
call CARMAGAS_Create(carma, I_GAS_H2O, "Water Vapor", WTMOL_H2O, &
I_VAPRTN_H2O_MURPHY2005, I_GCOMP_H2O, rc, shortname="Q", &
ds_threshold=0.2_f)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGAS_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGAS_Create failed.')
call CARMAGAS_Create(carma, I_GAS_H2SO4, "Sulfuric Acid", WTMOL_H2SO4, &
I_VAPRTN_H2SO4_AYERS1980, I_GCOMP_H2SO4, rc, shortname = "H2SO4", &
ds_threshold=-0.2_f)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGAS_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGAS_Create failed.')
! Define the Processes
call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_DUST, I_GRP_DUST, I_COLLEC_DATA, rc)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.')
! Set H2SO4 to be the condensing gas, water vapor is assumed to be in equilibrium
! and will be used to define the wet particle radius.
call CARMA_AddGrowth(carma, I_ELEM_SULFATE, I_GAS_H2SO4, rc)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddGrowth failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddGrowth failed.')
call CARMA_AddNucleation(carma, I_ELEM_SULFATE, I_ELEM_SULFATE, I_HOMNUC, 0._f, rc, igas=I_GAS_H2SO4)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddNucleation failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddNucleation failed.')
! Also need nucleation with meteor smoke.
call CARMA_AddNucleation(carma, I_ELEM_DUST, I_ELEM_SULCORE, I_HETNUCSULF, 0._f, rc, igas=I_GAS_H2SO4, ievp2elem=I_ELEM_DUST)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddNucleation failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddNucleation failed.')
call CARMA_AddCoagulation(carma, I_GRP_SULFATE, I_GRP_SULFATE, I_GRP_SULFATE, I_COLLEC_FUCHS, rc)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.')
! Dust-Sulfate Coagulation?
call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_SULFATE, I_GRP_SULFATE, I_COLLEC_FUCHS, rc)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.')
return
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -251,7 +260,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair
@@ -276,14 +285,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -309,14 +318,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! code to determine the mass in each bin from the CAM state.
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use camsrfexch, only: cam_out_t
@@ -347,10 +356,10 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
! code to determine the bulk mass from the CARMA state.
return
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -369,6 +378,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
integer :: ilat ! latitude index
@@ -508,7 +518,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
end if
end do
- if (abs((state%lat(icol) / DEG2RAD) - 90.0) <= 0.00001_r8) then
+ if (abs((state%lat(icol) / DEG2RAD) - 90.0_r8) <= 0.00001_r8) then
rfScale(icol) = carma_escale_grf(carma_escale_nLats, doy)
end if
@@ -560,7 +570,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
end if
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -568,7 +578,7 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use constituents, only: pcnst
use ioFileMod, only: getfil
use wrap_nf
@@ -578,6 +588,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
type(carma_type), intent(in) :: carma !! the carma object
logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer, intent(out) :: rc !! return code, negative indicates failure
integer :: ilev ! level index
@@ -603,7 +614,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! Add initialization here.
call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT)
- if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.")
+ if (rc < 0) call endrun("CARMAMODEL_InitializeModel: CARMA_Get failed.")
! Initialize the emissions rate table.
if (carma_do_emission) then
@@ -644,7 +655,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
carma_emis_ilev_max = carma_emis_nLevs
do ilev = 1, carma_emis_nLevs
- if (carma_emis_rate(ilev) <= 0.0) then
+ if (carma_emis_rate(ilev) <= 0.0_r8) then
carma_emis_ilev_min = ilev + 1
else
exit
@@ -652,7 +663,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
end do
do ilev = carma_emis_nLevs, 1, -1
- if (carma_emis_rate(ilev) <= 0.0) then
+ if (carma_emis_rate(ilev) <= 0.0_r8) then
carma_emis_ilev_max = ilev - 1
else
exit
@@ -721,7 +732,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! There should be one time for each day of the year, so
! quit if it isn't correct.
if (carma_escale_nTimes .ne. 365) then
- call endrun("CARMA_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.")
+ call endrun("CARMAMODEL_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.")
endif
call wrap_inq_dimid(fid, "ltime", ltime_did)
@@ -744,7 +755,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
call wrap_inq_varid(fid, 'SGRF', grf_vid)
tmp = nf90_get_var (fid, grf_vid, carma_escale_grf)
if (tmp/=NF90_NOERR) then
- write(iulog,*) 'CARMA_InitializeModel: error reading varid =', grf_vid
+ write(iulog,*) 'CARMAMODEL_InitializeModel: error reading varid =', grf_vid
call handle_error (tmp)
end if
@@ -780,7 +791,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
endif
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -792,8 +803,9 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
+ use pmgrid, only: plat, plev, plon
implicit none
@@ -814,15 +826,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
! NOTE: Initialized to 0. by the caller, so nothing needs to be done.
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
!! wet deposition of CARMA aerosols to the aerosols being communicated to the surface.
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -841,6 +893,121 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
rc = RC_OK
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
+
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ integer :: icol !! column index
+ integer :: ibin !! bin index
+ real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s
+ real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s
+ character(len=16) :: binname !! names bins
+ real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer :: i
+ integer :: icnst !! constituent index
+ integer :: ienconc !! concentration element index
+ integer :: ncore !! number of cores
+ integer :: icorelem(NELEM) !! core element index
+ real(r8) :: mair(pver) !! Mass of air column (kg/m2)
+ real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2)
+ real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2)
+ real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s)
+ real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s)
+ real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2)
+ real(r8) :: so2(pcols) !! SO2 gas (kg/m2)
+ real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2)
+ real(r8) :: bddust(pcols) !! Burden dust (kg/m2)
+ real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2)
+ real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2)
+ real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2)
+ character(len=16) :: shortname
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/pmc/carma_model_mod.F90 b/src/physics/carma/models/pmc/carma_model_mod.F90
index eb8c6e6667..41ac20fffe 100644
--- a/src/physics/carma/models/pmc/carma_model_mod.F90
+++ b/src/physics/carma/models/pmc/carma_model_mod.F90
@@ -45,14 +45,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 2 !! Number of particle groups
@@ -65,6 +70,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -117,7 +126,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
use ioFileMod, only: getfil
use wrap_nf
@@ -137,7 +146,7 @@ subroutine CARMA_DefineModel(carma, rc)
integer :: imag_vid
character(len=256) :: efile ! refractive index file name
real(kind=f) :: interp
- complex(kind=f) :: refidx_ice(NWAVE) ! the refractive index at each CAM wavelength
+ complex(kind=f) :: refidx_ice(NWAVE,NREFIDX) ! the refractive index at each CAM wavelength
integer :: LUNOPRT
logical :: do_print
@@ -145,7 +154,7 @@ subroutine CARMA_DefineModel(carma, rc)
rc = RC_OK
call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT, wave=wave)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_Get failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.')
! Report model specific configuration parameters.
if (masterproc) then
@@ -203,7 +212,7 @@ subroutine CARMA_DefineModel(carma, rc)
! Read in the tables.
call wrap_inq_varid(fid, 'wavelength', wave_vid)
call wrap_get_var_realx(fid, wave_vid, warren_wave)
- warren_wave = warren_wave * 1e-4 ! um -> cm
+ warren_wave = warren_wave * 1e-4_r8 ! um -> cm
call wrap_inq_varid(fid, 'm_real', real_vid)
call wrap_get_var_realx(fid, real_vid, warren_real)
@@ -227,10 +236,10 @@ subroutine CARMA_DefineModel(carma, rc)
if (wave(i) > warren_wave(j)) then
if (j > 1) then
interp = (wave(i) - warren_wave(j-1)) / (warren_wave(j) - warren_wave(j-1))
- refidx_ice(i) = cmplx(warren_real(j-1) + interp*(warren_real(j) - warren_real(j-1)), &
- warren_imag(j-1) + interp*(warren_imag(j) - warren_imag(j-1)))
+ refidx_ice(i,1) = cmplx(warren_real(j-1) + interp*(warren_real(j) - warren_real(j-1)), &
+ warren_imag(j-1) + interp*(warren_imag(j) - warren_imag(j-1)), kind=f)
else
- refidx_ice(i) = cmplx(warren_real(j), warren_imag(j))
+ refidx_ice(i,1) = cmplx(warren_real(j), warren_imag(j), kind=f)
endif
exit
@@ -240,8 +249,8 @@ subroutine CARMA_DefineModel(carma, rc)
end if
call CARMAGROUP_Create(carma, I_GRP_CRICE, "ice crystal", rmin, 2.2_f, I_SPHERE, 1._f, .true., &
- rc, do_mie=carma_do_pheat, refidx=refidx_ice, shortname="CRICE")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ rc, do_mie=carma_do_pheat, shortname="CRICE")
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
! Define the Elements
@@ -250,15 +259,15 @@ subroutine CARMA_DefineModel(carma, rc)
! should be 6 characters or less and without spaces.
call CARMAELEMENT_Create(carma, I_ELEM_DUST, I_GRP_DUST, "meteor smoke", RHO_METEOR_SMOKE, &
I_INVOLATILE, I_METEOR_SMOKE, rc, shortname="DUST")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
call CARMAELEMENT_Create(carma, I_ELEM_CRICE, I_GRP_CRICE, "ice crystal", RHO_I, &
- I_VOLATILE, I_ICE, rc, shortname="CRICE")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ I_VOLATILE, I_ICE, rc, shortname="CRICE", refidx=refidx_ice)
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
call CARMAELEMENT_Create(carma, I_ELEM_CRCORE, I_GRP_CRICE, "ice core", RHO_METEOR_SMOKE, &
I_COREMASS, I_METEOR_SMOKE, rc, shortname="CRCORE")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
! Define the Solutes
@@ -267,25 +276,25 @@ subroutine CARMA_DefineModel(carma, rc)
! Define the Gases
call CARMAGAS_Create(carma, I_GAS_H2O, "Water Vapor", WTMOL_H2O, &
I_VAPRTN_H2O_MURPHY2005, I_GCOMP_H2O, rc, shortname="Q", ds_threshold=0.2_f)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGAS_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGAS_Create failed.')
! Define the Processes
call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_DUST, I_GRP_DUST, I_COLLEC_DATA, rc)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.')
call CARMA_AddNucleation(carma, I_ELEM_DUST, I_ELEM_CRCORE, I_HETNUC, 0._f, rc, &
igas=I_GAS_H2O, ievp2elem=I_ELEM_DUST)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddNucleation failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddNucleation failed.')
call CARMA_AddGrowth(carma, I_ELEM_CRICE, I_GAS_H2O, rc)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddGrowth failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddGrowth failed.')
call CARMA_AddCoagulation(carma, I_GRP_DUST, I_GRP_CRICE, I_GRP_CRICE, I_COLLEC_DATA, rc)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.')
return
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -295,7 +304,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair
@@ -320,14 +329,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -353,14 +362,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! code to determine the mass in each bin from the CAM state.
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use camsrfexch, only: cam_out_t
@@ -391,10 +400,10 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
! code to determine the bulk mass from the CARMA state.
return
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -413,6 +422,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
integer :: ilat ! latitude index
@@ -552,7 +562,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
end if
end do
- if (abs((state%lat(icol) / DEG2RAD) - 90.0) <= 0.00001_r8) then
+ if (abs((state%lat(icol) / DEG2RAD) - 90.0_r8) <= 0.00001_r8) then
rfScale(icol) = carma_escale_grf(carma_escale_nLats, doy)
end if
@@ -598,7 +608,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
end if
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -606,7 +616,7 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use ioFileMod, only: getfil
use constituents, only: pcnst
use wrap_nf
@@ -616,6 +626,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
type(carma_type), intent(in) :: carma !! the carma object
logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer, intent(out) :: rc !! return code, negative indicates failure
integer :: ilev ! level index
@@ -641,7 +652,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! Add initialization here.
call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT)
- if (rc < 0) call endrun("CARMA_InitializeModel: CARMA_Get failed.")
+ if (rc < 0) call endrun("CARMAMODEL_InitializeModel: CARMA_Get failed.")
! Initialize the emissions rate table.
if (carma_do_emission) then
@@ -682,7 +693,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
carma_emis_ilev_max = carma_emis_nLevs
do ilev = 1, carma_emis_nLevs
- if (carma_emis_rate(ilev) <= 0.0) then
+ if (carma_emis_rate(ilev) <= 0.0_r8) then
carma_emis_ilev_min = ilev + 1
else
exit
@@ -690,7 +701,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
end do
do ilev = carma_emis_nLevs, 1, -1
- if (carma_emis_rate(ilev) <= 0.0) then
+ if (carma_emis_rate(ilev) <= 0.0_r8) then
carma_emis_ilev_max = ilev - 1
else
exit
@@ -759,7 +770,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! There should be one time for each day of the year, so
! quit if it isn't correct.
if (carma_escale_nTimes .ne. 365) then
- call endrun("CARMA_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.")
+ call endrun("CARMAMODEL_InitializeModel: Emission scaling file should have entries for 365 days, but doesn't.")
endif
call wrap_inq_dimid(fid, "ltime", ltime_did)
@@ -782,7 +793,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
call wrap_inq_varid(fid, 'SGRF', grf_vid)
tmp = nf90_get_var (fid, grf_vid, carma_escale_grf)
if (tmp/=NF90_NOERR) then
- write(iulog,*) 'CARMA_InitializeModel: error reading varid =', grf_vid
+ write(iulog,*) 'CARMAMODEL_InitializeModel: error reading varid =', grf_vid
call handle_error (tmp)
end if
@@ -818,7 +829,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
endif
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -830,8 +841,9 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
+ use pmgrid, only: plat, plev, plon
implicit none
@@ -852,15 +864,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
! NOTE: Initialized to 0. by the caller, so nothing needs to be done.
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
!! wet deposition of CARMA aerosols to the aerosols being communicated to the surface.
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -879,6 +931,121 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
rc = RC_OK
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
+
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ integer :: icol !! column index
+ integer :: ibin !! bin index
+ real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s
+ real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s
+ character(len=16) :: binname !! names bins
+ real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer :: i
+ integer :: icnst !! constituent index
+ integer :: ienconc !! concentration element index
+ integer :: ncore !! number of cores
+ integer :: icorelem(NELEM) !! core element index
+ real(r8) :: mair(pver) !! Mass of air column (kg/m2)
+ real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2)
+ real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2)
+ real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s)
+ real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s)
+ real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2)
+ real(r8) :: so2(pcols) !! SO2 gas (kg/m2)
+ real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2)
+ real(r8) :: bddust(pcols) !! Burden dust (kg/m2)
+ real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2)
+ real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2)
+ real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2)
+ character(len=16) :: shortname
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/pmc_sulfate/carma_model_mod.F90 b/src/physics/carma/models/pmc_sulfate/carma_model_mod.F90
index 4a9e08d5be..166bb66f3d 100644
--- a/src/physics/carma/models/pmc_sulfate/carma_model_mod.F90
+++ b/src/physics/carma/models/pmc_sulfate/carma_model_mod.F90
@@ -223,7 +223,7 @@ subroutine CARMA_DefineModel(carma, rc)
! Read in the tables.
call wrap_inq_varid(fid, 'wavelength', wave_vid)
call wrap_get_var_realx(fid, wave_vid, warren_wave)
- warren_wave = warren_wave * 1e-4 ! um -> cm
+ warren_wave = warren_wave * 1e-4_r8 ! um -> cm
call wrap_inq_varid(fid, 'm_real', real_vid)
call wrap_get_var_realx(fid, real_vid, warren_real)
@@ -617,7 +617,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
end if
end do
- if (abs((state%lat(icol) / DEG2RAD) - 90.0) <= 0.00001_r8) then
+ if (abs((state%lat(icol) / DEG2RAD) - 90.0_r8) <= 0.00001_r8) then
rfScale(icol) = carma_escale_grf(carma_escale_nLats, doy)
end if
@@ -753,7 +753,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
carma_emis_ilev_max = carma_emis_nLevs
do ilev = 1, carma_emis_nLevs
- if (carma_emis_rate(ilev) <= 0.0) then
+ if (carma_emis_rate(ilev) <= 0.0_r8) then
carma_emis_ilev_min = ilev + 1
else
exit
@@ -761,7 +761,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
end do
do ilev = carma_emis_nLevs, 1, -1
- if (carma_emis_rate(ilev) <= 0.0) then
+ if (carma_emis_rate(ilev) <= 0.0_r8) then
carma_emis_ilev_max = ilev - 1
else
exit
@@ -953,4 +953,4 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
return
end subroutine CARMA_WetDeposition
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/sea_salt/carma_model_mod.F90 b/src/physics/carma/models/sea_salt/carma_model_mod.F90
index db01fb4b00..0f1aa889dd 100644
--- a/src/physics/carma/models/sea_salt/carma_model_mod.F90
+++ b/src/physics/carma/models/sea_salt/carma_model_mod.F90
@@ -44,14 +44,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 1 !! Number of particle groups
@@ -64,6 +69,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -83,7 +92,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
type(carma_type), intent(inout) :: carma !! the carma object
integer, intent(out) :: rc !! return code, negative indicates failure
@@ -100,7 +109,7 @@ subroutine CARMA_DefineModel(carma, rc)
! Report model specific configuration parameters.
if (masterproc) then
call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_Get failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.')
if (do_print) write(LUNOPRT,*) ''
if (do_print) write(LUNOPRT,*) 'CARMA ', trim(carma_model), ' specific settings :'
@@ -117,7 +126,7 @@ subroutine CARMA_DefineModel(carma, rc)
rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, &
scavcoef=0.1_f, shortname="SALT", irhswell=I_GERBER, &
irhswcomp=I_SWG_SEA_SALT)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.')
! Define the Elements
@@ -125,7 +134,7 @@ subroutine CARMA_DefineModel(carma, rc)
! NOTE: For CAM, the optional shortname needs to be provided for the group. These names
! should be 6 characters or less and without spaces.
call CARMAELEMENT_Create(carma, 1, 1, "sea salt", RHO_SALT, I_INVOLATILE, I_SEA_SALT, rc, shortname="SALT")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
! Define the Solutes
@@ -137,7 +146,7 @@ subroutine CARMA_DefineModel(carma, rc)
! Define the Processes
return
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -147,7 +156,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair
@@ -172,14 +181,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -205,14 +214,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! code to determine the mass in each bin from the CAM state.
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use camsrfexch, only: cam_out_t
@@ -243,7 +252,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
! code to determine the bulk mass from the CARMA state.
return
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
!! Calculates the emissions for CARMA aerosol particles. By default, there is no
@@ -252,7 +261,7 @@ end subroutine CARMA_DiagnoseBulk
!!
!! @author Tianyi Fan, Chuck Bardeen
!! @version Dec-2010
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -270,6 +279,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
integer :: lchnk ! chunk identifier
@@ -439,7 +449,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
!**********************************
! wet sea salt radius at RH = 80%
!**********************************
- r80cm = (c1 * (r(ibin)) ** c2 / (c3 * r(ibin) ** c4 - log10(0.8)) + (r(ibin))**3) ** (1./3.) ! [cm]
+ r80cm = (c1 * (r(ibin)) ** c2 / (c3 * r(ibin) ** c4 - log10(0.8_r8)) + (r(ibin))**3) ** (1._r8/3._r8) ! [cm]
rdrycm = r(ibin) ! [cm]
r80 = r80cm *1.e4_r8 ! [um]
rdry = rdrycm*1.e4_r8 ! [um]
@@ -452,7 +462,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
!**********************************
! WIND for seasalt production
!**********************************
- call CARMA_SurfaceWind(carma, state, icol, cam_in, u10in, rc)
+ call CARMAMODEL_SurfaceWind(carma, state, icol, cam_in, u10in, rc)
! Add any surface flux here.
ncflx = 0.0_r8
@@ -542,7 +552,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
!Monahan
B_mona = (0.38_r8 - log10(r80)) / 0.65_r8
Monahan = 1.373_r8 * (u10in**3.41_r8) * r80**(-3._r8) * &
- (1._r8 + 0.057 *r80**1.05_r8) * 10._r8 ** (1.19_r8 * exp(-1. * B_mona**2)) ! dF/dr
+ (1._r8 + 0.057_r8 *r80**1.05_r8) * 10._r8 ** (1.19_r8 * exp(-1._r8 * B_mona**2)) ! dF/dr
!Smith
u14 = u10in * (1._r8 + cd_smith**0.5_r8 / xkar * log(14._r8 / 10._r8)) ! 14 meter wind
@@ -641,7 +651,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
end if
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -649,13 +659,14 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use constituents, only: pcnst
implicit none
type(carma_type), intent(in) :: carma !! the carma object
logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer, intent(out) :: rc !! return code, negative indicates failure
! Default return code.
@@ -664,7 +675,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! Add initialization here.
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -676,8 +687,9 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
+ use pmgrid, only: plat, plev, plon
implicit none
@@ -698,15 +710,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
! NOTE: Initialized to 0. by the caller, so nothing needs to be done.
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
!! wet deposition of CARMA aerosols to the aerosols being communicated to the surface.
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -725,14 +777,14 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
rc = RC_OK
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
!! Calculate the sea surface wind with a Weibull distribution.
!!
!! @author Tianyi Fan
!! @version August-2010
- subroutine CARMA_SurfaceWind(carma, state, icol, cam_in, u10in, rc)
+ subroutine CARMAMODEL_SurfaceWind(carma, state, icol, cam_in, u10in, rc)
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
use camsrfexch, only: cam_in_t
@@ -765,7 +817,7 @@ subroutine CARMA_SurfaceWind(carma, state, icol, cam_in, u10in, rc)
u10in = uWB341 ** (1._r8 / 3.41_r8)
return
- end subroutine CARMA_SurfaceWind
+ end subroutine CARMAMODEL_SurfaceWind
!! Calculate the nth mean of u using Weibull wind distribution
@@ -794,7 +846,7 @@ subroutine WeibullWind(u, uth, n, uwb, wbk)
if (present(wbk)) then
k = wbk
else
- k = 0.94*u**0.5_r8 ! follow Grini and Zender, 2004JGR
+ k = 0.94_r8*u**0.5_r8 ! follow Grini and Zender, 2004JGR
! k = 2.5_r8 ! Lansing's estimate
end if
@@ -809,4 +861,119 @@ subroutine WeibullWind(u, uth, n, uwb, wbk)
end subroutine WeibullWind
-end module
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the after timestep cloudborne aerosol diags
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ integer :: icol !! column index
+ integer :: ibin !! bin index
+ real(r8), pointer, dimension(:,:) :: soacm !! aerosol tendency due to gas-aerosol exchange kg/kg/s
+ real(r8), pointer, dimension(:,:) :: soapt !! aerosol tendency due to no2 photolysis kg/kg/s
+ character(len=16) :: binname !! names bins
+ real(r8) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer :: i
+ integer :: icnst !! constituent index
+ integer :: ienconc !! concentration element index
+ integer :: ncore !! number of cores
+ integer :: icorelem(NELEM) !! core element index
+ real(r8) :: mair(pver) !! Mass of air column (kg/m2)
+ real(r8) :: pureso4(pcols) !! pure sulfate (kg/m2)
+ real(r8) :: mixso4(pcols) !! mix sulfate (kg/m2)
+ real(r8) :: cprflux(pcols) !! Surface Flux pure sulfate (kg/m2/s)
+ real(r8) :: cmxflux(pcols) !! Surface Flux mix sulfate (kg/m2/s)
+ real(r8) :: h2so4(pcols) !! H2SO4 gas (kg/m2)
+ real(r8) :: so2(pcols) !! SO2 gas (kg/m2)
+ real(r8) :: bdbc(pcols) !! Burden BC sulfate (kg/m2)
+ real(r8) :: bddust(pcols) !! Burden dust (kg/m2)
+ real(r8) :: bdoc(pcols) !! Burden OC sulfate (kg/m2)
+ real(r8) :: bdsalt(pcols) !! Burden SALT sulfate (kg/m2)
+ real(r8) :: bdsoa(pcols) !! Burden SOA sulfate (kg/m2)
+ character(len=16) :: shortname
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
+
+end module carma_model_mod
diff --git a/src/physics/carma/models/sulfate/carma_model_mod.F90 b/src/physics/carma/models/sulfate/carma_model_mod.F90
index abf98d1820..c19e013891 100644
--- a/src/physics/carma/models/sulfate/carma_model_mod.F90
+++ b/src/physics/carma/models/sulfate/carma_model_mod.F90
@@ -38,15 +38,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
-
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 1 !! Number of particle groups
@@ -59,6 +63,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -90,7 +98,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
use physics_buffer, only: pbuf_add_field, dtype_r8
type(carma_type), intent(inout) :: carma !! the carma object
@@ -172,7 +180,7 @@ subroutine CARMA_DefineModel(carma, rc)
call pbuf_add_field('VOLC_MMR', 'global', dtype_r8, (/pcols, pver/), ipbuf4so4mmr)
endif
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -182,7 +190,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair
@@ -207,14 +215,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -240,14 +248,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! code to determine the mass in each bin from the CAM state.
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use camsrfexch, only: cam_out_t
use physics_buffer, only: pbuf_get_field
@@ -325,7 +333,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
end if
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
!! Calculates the emissions for CARMA aerosol particles. By default, there is no
@@ -334,7 +342,7 @@ end subroutine CARMA_DiagnoseBulk
!!
!! @author Tianyi Fan, Chuck Bardeen
!! @version Dec-2010
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -353,6 +361,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
! Default return code.
@@ -365,7 +374,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
tendency = 0._r8
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -373,20 +382,21 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use constituents, only : pcnst
implicit none
type(carma_type), intent(in) :: carma !! the carma object
logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer, intent(out) :: rc !! return code, negative indicates failure
! Default return code.
rc = RC_OK
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -398,7 +408,7 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
implicit none
@@ -420,7 +430,49 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
! NOTE: Initialized to 0. by the caller, so nothing needs to be done.
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+
+
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
@@ -428,7 +480,7 @@ end subroutine CARMA_InitializeParticle
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -447,6 +499,94 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
rc = RC_OK
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
+
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/test_detrain/carma_model_mod.F90 b/src/physics/carma/models/test_detrain/carma_model_mod.F90
index 16e6cb431f..fde34f8b20 100644
--- a/src/physics/carma/models/test_detrain/carma_model_mod.F90
+++ b/src/physics/carma/models/test_detrain/carma_model_mod.F90
@@ -472,4 +472,4 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
return
end subroutine CARMA_WetDeposition
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/test_growth/carma_model_mod.F90 b/src/physics/carma/models/test_growth/carma_model_mod.F90
index ad57aed469..5b4a2b6ac7 100644
--- a/src/physics/carma/models/test_growth/carma_model_mod.F90
+++ b/src/physics/carma/models/test_growth/carma_model_mod.F90
@@ -10,10 +10,10 @@
!! the initial conditions of the particles. Each realization of CARMA
!! microphysics has its own version of this file.
!!
-!! This file is a simple test case involving one group of dust particles and
-!! 8 size bins. Optical properties are calculated, assuming a constant refractive
-!! index of (1.55, 4e-3). The particles are not subject to particle swelling, but
-!! do coagulate.
+!! This file is a simple test case involving two groups: sulfate condensation nuclei
+!! and ice particles. The sulfates are prescribed and the ice is prognostics. This
+!! test exercises the nucleation and growth code. THe particles are sedimented, but
+!! do not coagulate.
!!
!! @version May-2009
!! @author Chuck Bardeen
@@ -43,14 +43,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 2 !! Number of particle groups
@@ -63,6 +68,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -93,7 +102,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
type(carma_type), intent(inout) :: carma !! the carma object
integer, intent(out) :: rc !! return code, negative indicates failure
@@ -118,11 +127,11 @@ subroutine CARMA_DefineModel(carma, rc)
call CARMAGROUP_Create(carma, I_GRP_CRCN, "Sulfate CN", rmin_cn, 4.0_f, I_SPHERE, 1._f, .false., &
rc, shortname="CRCN", cnsttype=I_CNSTTYPE_DIAGNOSTIC, &
do_vtran=.false.)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
call CARMAGROUP_Create(carma, I_GRP_CRICE, "Ice", rmin_ice, 2.8_f, I_HEXAGON, 1._f / 6._f, .true., &
rc, shortname="CRICE", ifallrtn=I_FALLRTN_STD_SHAPE)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
@@ -132,30 +141,30 @@ subroutine CARMA_DefineModel(carma, rc)
! should be 6 characters or less and without spaces.
call CARMAELEMENT_Create(carma, I_ELEM_CRCN, I_GRP_CRCN, "Sulfate CN", RHO_CN, &
I_INVOLATILE, I_H2SO4, rc, shortname="CRCN", isolute=I_SOL_CRH2SO4)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, I_ELEM_CRICE, I_GRP_CRICE, "Ice", RHO_I, &
I_VOLATILE, I_ICE, rc, shortname="CRICE")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, I_ELEM_CRCORE, I_GRP_CRICE, "Core Mass", RHO_CN, &
I_COREMASS, I_H2SO4, rc, shortname="CRCORE", isolute=1)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
! Define the Solutes
call CARMASOLUTE_Create(carma, I_SOL_CRH2SO4, "Sulfuric Acid", 2, 98._f, 1.38_f, rc, shortname="CRH2SO4")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMASOLUTE_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMASOLUTE_Create failed.')
! Define the Gases
call CARMAGAS_Create(carma, I_GAS_H2O, "Water Vapor", WTMOL_H2O, I_VAPRTN_H2O_MURPHY2005, I_GCOMP_H2O, rc, shortname="Q")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGAS_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGAS_Create failed.')
! Define the Processes
call CARMA_AddGrowth(carma, I_ELEM_CRICE, I_GAS_H2O, rc)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddGrowth failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddGrowth failed.')
! NOTE: For now, assume the latent heat for nucleation is the latent of of fusion of
! water, using the CAM constant (scaled from J/kg to erg/g).
@@ -165,10 +174,10 @@ subroutine CARMA_DefineModel(carma, rc)
! the gas associated with nucleation is accounted for.
call CARMA_AddNucleation(carma, I_ELEM_CRCN, I_ELEM_CRCORE, &
I_AERFREEZE + I_AF_KOOP_2000, 0._f, rc, igas=I_GAS_H2O, ievp2elem=I_ELEM_CRCN)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_AddNucleation failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_AddNucleation failed.')
return
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -178,7 +187,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair
@@ -203,14 +212,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -249,7 +258,7 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! Get the air density.
call CARMASTATE_GetState(cstate, rc, rhoa_wet=rhoa_wet)
- if (rc < RC_OK) call endrun('CARMA_DiagnoseBins::CARMASTATE_GetState failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DiagnoseBins::CARMASTATE_GetState failed.')
! Use a fixed sulfate size distribution. By doing this as a diagnostic group,
! the constituents for the sulfate bins do not need to be advected, which
@@ -258,7 +267,7 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
ielem = 1
call CARMAGROUP_Get(carma, igroup, rc, r=r, dr=dr, rmass=rmass)
- if (rc < RC_OK) call endrun('CARMA_DiagnoseBins::CARMAGROUP_Get failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DiagnoseBins::CARMAGROUP_Get failed.')
arg1(:) = n * dr(:) / (sqrt(2._f*PI) * r(:) * log(rsig))
arg2(:) = -((log(r(:)) - log(r0))**2) / (2._f*(log(rsig))**2)
@@ -268,18 +277,18 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
do ibin = 1, NBIN
mmr(ibin, :) = rhop(ibin) / rhoa_wet(:)
call CARMASTATE_SetBin(cstate, ielem, ibin, mmr(ibin, :), rc)
- if (rc < RC_OK) call endrun('CARMA_DiagnoseBins::CARMAGROUP_SetBin failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DiagnoseBins::CARMAGROUP_SetBin failed.')
end do
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use camsrfexch, only: cam_out_t
@@ -310,7 +319,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
! code to determine the bulk mass from the CARMA state.
return
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
!! Calculates the emissions for CARMA aerosol particles. By default, there is no
@@ -319,7 +328,7 @@ end subroutine CARMA_DiagnoseBulk
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -338,6 +347,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
integer :: ncol ! number of columns in chunk
@@ -370,7 +380,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
tendency(:ncol, :pver) = 0.0_r8
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -381,13 +391,14 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use constituents, only : pcnst
implicit none
type(carma_type), intent(in) :: carma !! the carma object
logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer, intent(out) :: rc !! return code, negative indicates failure
! Default return code.
@@ -396,7 +407,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! Add initialization here.
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -408,7 +419,7 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use pmgrid, only: plev
@@ -431,31 +442,65 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
! Put a horizontally uniform layer of the smallest bin size
! in the model.
if (ibin == 1) then
- if (ielem == I_ELEM_CRICE) then
- where(mask)
- q(:, plev/4) = 100e-7_r8 ! 1/4
- end where
- end if
- if (ielem == I_ELEM_CRCORE) then
- where(mask)
- q(:, plev/4) = 100e-9_r8 ! 1/4
- end where
- end if
+ where(mask)
+! q(:, 1) = 100e-9_r8 ! top
+ q(:, plev/4) = 100e-9_r8 ! 1/4
! q(:, plev/2) = 100e-9_r8 ! middle
! q(:, 3*plev/4) = 100e-9_r8 ! 3/4
! q(:, plev-1) = 100e-9_r8 ! bottom
+ end where
end if
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
!! wet deposition of CARMA aerosols to the aerosols being communicated to the surface.
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -474,6 +519,94 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
rc = RC_OK
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
+
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/test_passive/carma_model_mod.F90 b/src/physics/carma/models/test_passive/carma_model_mod.F90
index 12f4a6168e..150f1d8a5f 100644
--- a/src/physics/carma/models/test_passive/carma_model_mod.F90
+++ b/src/physics/carma/models/test_passive/carma_model_mod.F90
@@ -42,14 +42,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 1 !! Number of particle groups
@@ -62,6 +67,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -79,7 +88,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
type(carma_type), intent(inout) :: carma !! the carma object
integer, intent(out) :: rc !! return code, negative indicates failure
@@ -101,7 +110,7 @@ subroutine CARMA_DefineModel(carma, rc)
call CARMAGROUP_Create(carma, 1, "Dust", rmin, vmrat, I_SPHERE, 1._f, .false., &
rc, do_wetdep=.true., do_drydep=.true., solfac=0.15_f, &
scavcoef=0.1_f, shortname="DUST")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.')
! Define the Elements
@@ -109,7 +118,7 @@ subroutine CARMA_DefineModel(carma, rc)
! NOTE: For CAM, the optional shortname needs to be provided for the group. These names
! should be 6 characters or less and without spaces.
call CARMAELEMENT_Create(carma, 1, 1, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="DUST")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
! Define the Solutes
@@ -120,10 +129,10 @@ subroutine CARMA_DefineModel(carma, rc)
! Define the Processes
call CARMA_AddCoagulation(carma, 1, 1, 1, I_COLLEC_DATA, rc)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.')
return
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -133,7 +142,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair
@@ -158,14 +167,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -191,14 +200,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! code to determine the mass in each bin from the CAM state.
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use camsrfexch, only: cam_out_t
@@ -229,7 +238,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
! code to determine the bulk mass from the CARMA state.
return
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
!! Calculates the emissions for CARMA aerosol particles. By default, there is no
@@ -238,7 +247,7 @@ end subroutine CARMA_DiagnoseBulk
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -257,6 +266,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
integer :: ncol ! number of columns in chunk
@@ -289,7 +299,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
tendency(:ncol, :pver) = 0.0_r8
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -300,13 +310,14 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use constituents, only : pcnst
implicit none
type(carma_type), intent(in) :: carma !! the carma object
logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer, intent(out) :: rc !! return code, negative indicates failure
! Default return code.
@@ -315,7 +326,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! Add initialization here.
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -327,7 +338,7 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use pmgrid, only: plev
@@ -360,15 +371,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
end if
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
!! wet deposition of CARMA aerosols to the aerosols being communicated to the surface.
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -387,6 +438,95 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
rc = RC_OK
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
+
+
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/test_radiative/carma_model_mod.F90 b/src/physics/carma/models/test_radiative/carma_model_mod.F90
index 8acff28edb..d1b248df5a 100644
--- a/src/physics/carma/models/test_radiative/carma_model_mod.F90
+++ b/src/physics/carma/models/test_radiative/carma_model_mod.F90
@@ -42,14 +42,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 1 !! Number of particle groups
@@ -65,6 +70,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH) = (/ 0._f, 0.5_f, 0.7_f, 0.8_f, 0.9_f, 0.95_f, 0.98_f, 0.99_f /)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -82,7 +91,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
type(carma_type), intent(inout) :: carma !! the carma object
integer, intent(out) :: rc !! return code, negative indicates failure
@@ -90,14 +99,14 @@ subroutine CARMA_DefineModel(carma, rc)
real(kind=f), parameter :: RHO_DUST = 2.0_f ! density of dust particles (g/cm)
real(kind=f), parameter :: rmin = 1e-5_f ! minimum radius (cm)
real(kind=f), parameter :: vmrat = 2.0_f ! volume ratio
- complex(kind=f) :: refidx(NWAVE) ! refractice indices
+ complex(kind=f) :: refidx(NWAVE, NREFIDX) ! refractice indices
! Default return code.
rc = RC_OK
! Use the same refractive index at all wavelengths. This value is typical of dust in
! the visible.
- refidx(:) = (1.55_f, 4e-3_f)
+ refidx(:,1) = (1.55_f, 4e-3_f)
! Define the Groups
!
@@ -108,16 +117,16 @@ subroutine CARMA_DefineModel(carma, rc)
! should also be defined.
call CARMAGROUP_Create(carma, 1, "Dust", rmin, vmrat, I_SPHERE, 1._f, .false., &
rc, do_wetdep=.true., do_drydep=.true., solfac=0.15_f, &
- scavcoef=0.1_f, shortname="DUST", refidx=refidx, do_mie=.true.)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.')
+ scavcoef=0.1_f, shortname="DUST", do_mie=.true.)
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.')
! Define the Elements
!
! NOTE: For CAM, the optional shortname needs to be provided for the group. These names
! should be 6 characters or less and without spaces.
- call CARMAELEMENT_Create(carma, 1, 1, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="DUST")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ call CARMAELEMENT_Create(carma, 1, 1, "Dust", RHO_DUST, I_INVOLATILE, I_DUST, rc, shortname="DUST", refidx=refidx)
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
! Define the Solutes
@@ -128,10 +137,10 @@ subroutine CARMA_DefineModel(carma, rc)
! Define the Processes
call CARMA_AddCoagulation(carma, 1, 1, 1, I_COLLEC_DATA, rc)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddCoagulation failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddCoagulation failed.')
return
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -141,7 +150,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair
@@ -166,14 +175,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -199,14 +208,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! code to determine the mass in each bin from the CAM state.
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use camsrfexch, only: cam_out_t
@@ -237,7 +246,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
! code to determine the bulk mass from the CARMA state.
return
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
!! Calculates the emissions for CARMA aerosol particles. By default, there is no
@@ -246,7 +255,7 @@ end subroutine CARMA_DiagnoseBulk
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -265,6 +274,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
integer :: ncol ! number of columns in chunk
@@ -297,7 +307,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
tendency(:ncol, :pver) = 0.0_r8
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -308,13 +318,14 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use constituents, only : pcnst
implicit none
type(carma_type), intent(in) :: carma !! the carma object
logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer, intent(out) :: rc !! return code, negative indicates failure
! Default return code.
@@ -323,7 +334,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! Add initialization here.
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -335,7 +346,7 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use pmgrid, only: plev
@@ -368,15 +379,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
end if
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
!! wet deposition of CARMA aerosols to the aerosols being communicated to the surface.
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -395,6 +446,94 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
rc = RC_OK
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
+
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/test_swelling/carma_model_mod.F90 b/src/physics/carma/models/test_swelling/carma_model_mod.F90
index ce55401475..4e98bb5cd1 100644
--- a/src/physics/carma/models/test_swelling/carma_model_mod.F90
+++ b/src/physics/carma/models/test_swelling/carma_model_mod.F90
@@ -43,14 +43,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 3 !! Number of particle groups
@@ -63,6 +68,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -80,7 +89,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
type(carma_type), intent(inout) :: carma !! the carma object
integer, intent(out) :: rc !! return code, negative indicates failure
@@ -100,19 +109,19 @@ subroutine CARMA_DefineModel(carma, rc)
call CARMAGROUP_Create(carma, 1, "None", rmin, vmrat, I_SPHERE, 1._f, .false., &
rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, &
scavcoef=0.1_f, shortname="SALT")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.')
call CARMAGROUP_Create(carma, 2, "Fitzgerald", rmin, vmrat, I_SPHERE, 1._f, &
.false., rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, &
scavcoef=0.1_f, shortname="SALTFZ", irhswell=I_FITZGERALD, &
irhswcomp=I_SWF_NACL)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.')
call CARMAGROUP_Create(carma, 3, "Gerber", rmin, vmrat, I_SPHERE, 1._f, &
.false., rc, do_wetdep=.true., do_drydep=.true., solfac=0.3_f, &
scavcoef=0.1_f, shortname="SALTGB", irhswell=I_GERBER, &
irhswcomp=I_SWG_SEA_SALT)
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddGroup failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddGroup failed.')
! Define the Elements
@@ -120,13 +129,13 @@ subroutine CARMA_DefineModel(carma, rc)
! NOTE: For CAM, the optional shortname needs to be provided for the group. These names
! should be 6 characters or less and without spaces.
call CARMAELEMENT_Create(carma, 1, 1, "None", RHO_SALT, I_INVOLATILE, I_SEA_SALT, rc, shortname="SALT")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
call CARMAELEMENT_Create(carma, 2, 2, "Fitz", RHO_SALT, I_INVOLATILE, I_SEA_SALT, rc, shortname="SALTFZ")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
call CARMAELEMENT_Create(carma, 3, 3, "Gerb", RHO_SALT, I_INVOLATILE, I_SEA_SALT, rc, shortname="SALTGB")
- if (rc < 0) call endrun('CARMA_DefineModel::CARMA_AddElement failed.')
+ if (rc < 0) call endrun('CARMAMODEL_DefineModel::CARMA_AddElement failed.')
! Define the Solutes
@@ -138,7 +147,7 @@ subroutine CARMA_DefineModel(carma, rc)
! Define the Processes
return
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -148,7 +157,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair
@@ -173,14 +182,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -206,14 +215,14 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! code to determine the mass in each bin from the CAM state.
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use camsrfexch, only: cam_out_t
@@ -244,7 +253,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
! code to determine the bulk mass from the CARMA state.
return
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
!! Calculates the emissions for CARMA aerosol particles. By default, there is no
@@ -253,7 +262,7 @@ end subroutine CARMA_DiagnoseBulk
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -272,6 +281,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
integer :: ncol ! number of columns in chunk
@@ -304,7 +314,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
tendency(:ncol, :pver) = 0.0_r8
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -312,13 +322,14 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use constituents, only : pcnst
implicit none
type(carma_type), intent(in) :: carma !! the carma object
logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer, intent(out) :: rc !! return code, negative indicates failure
! Default return code.
@@ -327,7 +338,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
! Add initialization here.
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -339,7 +350,7 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use pmgrid, only: plev
@@ -369,15 +380,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
end where
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
!! wet deposition of CARMA aerosols to the aerosols being communicated to the surface.
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -396,6 +447,95 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
rc = RC_OK
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
+
+
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/test_tracers/carma_model_mod.F90 b/src/physics/carma/models/test_tracers/carma_model_mod.F90
index 9ed84a9471..40aa2b911c 100644
--- a/src/physics/carma/models/test_tracers/carma_model_mod.F90
+++ b/src/physics/carma/models/test_tracers/carma_model_mod.F90
@@ -49,14 +49,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 6 !! Number of particle groups
@@ -69,6 +74,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -98,7 +107,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
type(carma_type), intent(inout) :: carma !! the carma object
integer, intent(out) :: rc !! return code, negative indicates failure
@@ -112,7 +121,7 @@ subroutine CARMA_DefineModel(carma, rc)
rc = RC_OK
call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_Get failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.')
! Report model specific configuration parameters.
if (masterproc) then
@@ -132,22 +141,22 @@ subroutine CARMA_DefineModel(carma, rc)
! defined. If wetdep is defined, then the optional solubility factor
! should also be defined.
call CARMAGROUP_Create(carma, 1, "Region 1", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG1")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
call CARMAGROUP_Create(carma, 2, "Region 2", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG2")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
call CARMAGROUP_Create(carma, 3, "Region 3", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG3")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
call CARMAGROUP_Create(carma, 4, "Region 4", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG4")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
call CARMAGROUP_Create(carma, 5, "Region 5", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG5")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
call CARMAGROUP_Create(carma, 6, "Rest of World", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG6")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
! Define the Elements
@@ -155,22 +164,22 @@ subroutine CARMA_DefineModel(carma, rc)
! NOTE: For CAM, the optional shortname needs to be provided for the group. These names
! should be 6 characters or less and without spaces.
call CARMAELEMENT_Create(carma, 1, 1, "Region 1", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG1")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, 2, 2, "Region 2", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG2")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, 3, 3, "Region 3", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG3")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, 4, 4, "Region 4", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG4")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, 5, 5, "Region 5", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG5")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, 6, 6, "Rest of World", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG6")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
! Define the Solutes
@@ -183,7 +192,7 @@ subroutine CARMA_DefineModel(carma, rc)
return
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -193,7 +202,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair, cappa
@@ -219,14 +228,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -252,7 +261,7 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! code to determine the mass in each bin from the CAM state.
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
@@ -262,7 +271,7 @@ end subroutine CARMA_DiagnoseBins
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
@@ -325,7 +334,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
end if
return
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
!! Calculates the emissions for CARMA aerosol particles.
@@ -352,7 +361,7 @@ end subroutine CARMA_DiagnoseBulk
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -372,6 +381,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
real(r8) :: lat(state%ncol) ! latitude (degrees)
@@ -489,7 +499,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
end if
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -500,20 +510,22 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use constituents, only : pcnst
+
implicit none
type(carma_type), intent(inout) :: carma !! the carma object
logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer, intent(out) :: rc !! return code, negative indicates failure
! Default return code.
rc = RC_OK
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -525,7 +537,7 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
implicit none
@@ -552,15 +564,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
end do
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
!! wet deposition of CARMA aerosols to the aerosols being communicated to the surface.
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -579,6 +631,93 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
rc = RC_OK
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/test_tracers2/carma_model_mod.F90 b/src/physics/carma/models/test_tracers2/carma_model_mod.F90
index ecb3324ed8..d6a74c4d12 100644
--- a/src/physics/carma/models/test_tracers2/carma_model_mod.F90
+++ b/src/physics/carma/models/test_tracers2/carma_model_mod.F90
@@ -49,14 +49,19 @@ module carma_model_mod
private
! Declare the public methods.
- public CARMA_DefineModel
- public CARMA_Detrain
- public CARMA_DiagnoseBins
- public CARMA_DiagnoseBulk
- public CARMA_EmitParticle
- public CARMA_InitializeModel
- public CARMA_InitializeParticle
- public CARMA_WetDeposition
+ public CARMAMODEL_CalculateCloudborneDiagnostics
+ public CARMAMODEL_CreateOpticsFile
+ public CARMAMODEL_DefineModel
+ public CARMAMODEL_Detrain
+ public CARMAMODEL_DiagnoseBins
+ public CARMAMODEL_DiagnoseBulk
+ public CARMAMODEL_EmitParticle
+ public CARMAMODEL_InitializeModel
+ public CARMAMODEL_InitializeParticle
+ public CARMAMODEL_OutputBudgetDiagnostics
+ public CARMAMODEL_OutputCloudborneDiagnostics
+ public CARMAMODEL_OutputDiagnostics
+ public CARMAMODEL_WetDeposition
! Declare public constants
integer, public, parameter :: NGROUP = 7 !! Number of particle groups
@@ -69,6 +74,10 @@ module carma_model_mod
integer, public, parameter :: NMIE_RH = 8 !! Number of relative humidities for mie calculations
real(kind=f), public :: mie_rh(NMIE_RH)
+ integer, public, parameter :: NMIE_WTP = 0 !! Number of weight percents for mie calculations
+ real(kind=f), public :: mie_wtp(NMIE_WTP)
+ integer, public, parameter :: NREFIDX = 1 !! Number of refractive indices per element
+
! Defines whether the groups should undergo deep convection in phase 1 or phase 2.
! Water vapor and cloud particles are convected in phase 1, while all other constituents
! are done in phase 2.
@@ -99,7 +108,7 @@ module carma_model_mod
!!
!! @version May-2009
!! @author Chuck Bardeen
- subroutine CARMA_DefineModel(carma, rc)
+ subroutine CARMAMODEL_DefineModel(carma, rc)
type(carma_type), intent(inout) :: carma !! the carma object
integer, intent(out) :: rc !! return code, negative indicates failure
@@ -113,7 +122,7 @@ subroutine CARMA_DefineModel(carma, rc)
rc = RC_OK
call CARMA_Get(carma, rc, do_print=do_print, LUNOPRT=LUNOPRT)
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMA_Get failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMA_Get failed.')
! Report model specific configuration parameters.
if (masterproc) then
@@ -133,25 +142,25 @@ subroutine CARMA_DefineModel(carma, rc)
! defined. If wetdep is defined, then the optional solubility factor
! should also be defined.
call CARMAGROUP_Create(carma, 1, "Region 1", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG1")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
call CARMAGROUP_Create(carma, 2, "Region 2", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG2")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
call CARMAGROUP_Create(carma, 3, "Region 3", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG3")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
call CARMAGROUP_Create(carma, 4, "Region 4", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG4")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
call CARMAGROUP_Create(carma, 5, "Region 5", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG5")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
call CARMAGROUP_Create(carma, 6, "Region 6", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG6")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
call CARMAGROUP_Create(carma, 7, "Rest of World", rmin, vmrat, I_SPHERE, 1._f, .True., rc, shortname="CRRG7")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAGROUP_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAGROUP_Create failed.')
! Define the Elements
@@ -159,25 +168,25 @@ subroutine CARMA_DefineModel(carma, rc)
! NOTE: For CAM, the optional shortname needs to be provided for the group. These names
! should be 6 characters or less and without spaces.
call CARMAELEMENT_Create(carma, 1, 1, "Region 1", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG1")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, 2, 2, "Region 2", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG2")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, 3, 3, "Region 3", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG3")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, 4, 4, "Region 4", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG4")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, 5, 5, "Region 5", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG5")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, 6, 6, "Region 6", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG6")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
call CARMAELEMENT_Create(carma, 7, 7, "Rest of World", WTMOL_AIR, I_INVOLATILE, I_INERT, rc, shortname="CRRG7")
- if (rc < RC_OK) call endrun('CARMA_DefineModel::CARMAElement_Create failed.')
+ if (rc < RC_OK) call endrun('CARMAMODEL_DefineModel::CARMAElement_Create failed.')
! Define the Solutes
@@ -190,7 +199,7 @@ subroutine CARMA_DefineModel(carma, rc)
return
- end subroutine CARMA_DefineModel
+ end subroutine CARMAMODEL_DefineModel
!! Defines all the CARMA components (groups, elements, solutes and gases) and process
@@ -200,7 +209,7 @@ end subroutine CARMA_DefineModel
!! @author Chuck Bardeen
!!
!! @see CARMASTATE_SetDetrain
- subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq, prec_str, snow_str, &
tnd_qsnow, tnd_nsnow)
use camsrfexch, only: cam_in_t
use physconst, only: latice, latvap, cpair, cappa
@@ -226,14 +235,14 @@ subroutine CARMA_Detrain(carma, cstate, cam_in, dlf, state, icol, dt, rc, rliq,
rc = RC_OK
return
- end subroutine CARMA_Detrain
+ end subroutine CARMAMODEL_Detrain
!! For diagnostic groups, sets up up the CARMA bins based upon the CAM state.
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
+ subroutine CARMAMODEL_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, prec_str, snow_str)
use time_manager, only: is_first_step
implicit none
@@ -259,7 +268,7 @@ subroutine CARMA_DiagnoseBins(carma, cstate, state, pbuf, icol, dt, rc, rliq, pr
! code to determine the mass in each bin from the CAM state.
return
- end subroutine CARMA_DiagnoseBins
+ end subroutine CARMAMODEL_DiagnoseBins
!! For diagnostic groups, determines the tendencies on the CAM state from the CARMA bins.
@@ -269,7 +278,7 @@ end subroutine CARMA_DiagnoseBins
!!
!! @version July-2009
!! @author Chuck Bardeen
- subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
+ subroutine CARMAMODEL_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol, dt, rc, rliq, prec_str, snow_str, &
prec_sed, snow_sed, tnd_qsnow, tnd_nsnow, re_ice)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
@@ -332,7 +341,7 @@ subroutine CARMA_DiagnoseBulk(carma, cstate, cam_out, state, pbuf, ptend, icol,
end if
return
- end subroutine CARMA_DiagnoseBulk
+ end subroutine CARMAMODEL_DiagnoseBulk
!! Calculates the emissions for CARMA aerosol particles.
@@ -359,7 +368,7 @@ end subroutine CARMA_DiagnoseBulk
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, rc)
+ subroutine CARMAMODEL_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tendency, surfaceFlux, pbuf, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
use physics_types, only: physics_state
@@ -379,6 +388,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
type(cam_in_t), intent(in) :: cam_in !! surface inputs
real(r8), intent(out) :: tendency(pcols, pver) !! constituent tendency (kg/kg/s)
real(r8), intent(out) :: surfaceFlux(pcols) !! constituent surface flux (kg/m^2/s)
+ type(physics_buffer_desc), pointer :: pbuf(:) !! physics buffer
integer, intent(out) :: rc !! return code, negative indicates failure
real(r8) :: lat(state%ncol) ! latitude (degrees)
@@ -497,7 +507,7 @@ subroutine CARMA_EmitParticle(carma, ielem, ibin, icnst, dt, state, cam_in, tend
end if
return
- end subroutine CARMA_EmitParticle
+ end subroutine CARMAMODEL_EmitParticle
!! Allows the model to perform its own initialization in addition to what is done
@@ -508,20 +518,21 @@ end subroutine CARMA_EmitParticle
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeModel(carma, lq_carma, rc)
+ subroutine CARMAMODEL_InitializeModel(carma, lq_carma, pbuf2d, rc)
use constituents, only : pcnst
implicit none
type(carma_type), intent(inout) :: carma !! the carma object
logical, intent(inout) :: lq_carma(pcnst) !! flags to indicate whether the constituent
!! could have a CARMA tendency
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
integer, intent(out) :: rc !! return code, negative indicates failure
! Default return code.
rc = RC_OK
return
- end subroutine CARMA_InitializeModel
+ end subroutine CARMAMODEL_InitializeModel
!! Sets the initial condition for CARMA aerosol particles. By default, there are no
@@ -533,7 +544,7 @@ end subroutine CARMA_InitializeModel
!!
!! @author Chuck Bardeen
!! @version May-2009
- subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
+ subroutine CARMAMODEL_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask, q, rc)
use shr_kind_mod, only: r8 => shr_kind_r8
implicit none
@@ -560,15 +571,55 @@ subroutine CARMA_InitializeParticle(carma, ielem, ibin, latvals, lonvals, mask,
end do
return
- end subroutine CARMA_InitializeParticle
+ end subroutine CARMAMODEL_InitializeParticle
+
+ !! This routine is an extension of CARMA_CreateOpticsFile() that allows for
+ !! model specific tables to be created in addition to the model independent
+ !! methods that are in carma_intr.F90.
+ !!
+ !! The opticsType that is specified for the group determines how the optical
+ !! properties will be generated for that group. Each group can use a different
+ !! optics method if needed. Refractive indices need for these calculation are
+ !! are specified in the group's elements rather than at the group level. This
+ !! allows various mixing approaches to be used to determine the refractive index
+ !! for the particle as a whole. If the refractive index for water is needed,
+ !! it is specific the the CARMAGAS object for H2O.
+ subroutine CARMAMODEL_CreateOpticsFile(carma, igroup, opticsType, rc)
+
+ implicit none
+
+ type(carma_type), intent(inout) :: carma !! the carma object
+ integer, intent(in) :: igroup !! group identifier
+ integer, intent(in) :: opticsType !! optics type (see I_OPTICS_... in carma_enums.F90)
+ integer, intent(out) :: rc !! return code, negative indicates failure
+ ! Local variables
+ logical :: do_mie
+ integer :: cnsttype ! constituent type
+
+ ! Assume success.
+ rc = 0
+
+ ! What type of calculation is needed for this group?
+ !
+ ! NOTE: Some of these calculations generate optical properties as single mass
+ ! coefficients, while others are lookup tables designed around multiple
+ ! dimensions.
+ select case (opticsType)
+
+ case default
+ call endrun('carma_CreateOpticsFile:: Unknown optics type.')
+ end select
+
+ return
+ end subroutine CARMAMODEL_CreateOpticsFile
!! Called after wet deposition has been performed. Allows the specific model to add
!! wet deposition of CARMA aerosols to the aerosols being communicated to the surface.
!!
!! @version July-2011
!! @author Chuck Bardeen
- subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
+ subroutine CARMAMODEL_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
use camsrfexch, only: cam_out_t
implicit none
@@ -587,6 +638,94 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
rc = RC_OK
return
- end subroutine CARMA_WetDeposition
+ end subroutine CARMAMODEL_WetDeposition
+
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_CalculateCloudborneDiagnostics(carma, state, pbuf, aerclddiag, rc)
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(out) :: aerclddiag(pcols,MAXCLDAERDIAG) !! the total cloudborne aerosols, supports up to MAXCLDAERDIAG different values
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_CalculateCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputBudgetDiagnostics(carma, icnst4elem, icnst4gas, state, ptend, old_cflux, cflux, dt, pname, rc)
+ use cam_history, only: outfld
+ use constituents, only: pcnst, cnst_get_ind
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ integer, intent(in) :: icnst4gas(NGAS) !! constituent index for a carma gas
+ type(physics_state), intent(in) :: state !! Physics state variables - before pname
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ real(r8) :: old_cflux(pcols,pcnst) !! cam_in%clfux from before the timestep_tend
+ real(r8) :: cflux(pcols,pcnst) !! cam_in%clfux from after the timestep_tend
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputBudgetDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputCloudborneDiagnostics(carma, state, pbuf, dt, pname, oldaerclddiag, rc)
+ use cam_history, only: outfld
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ real(r8), intent(in) :: dt !! timestep (s)
+ character(*), intent(in) :: pname !! short name of the physics package
+ real(r8), intent(in ) :: oldaerclddiag(pcols,MAXCLDAERDIAG) !! the before timestep cloudborne aerosol diags
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputCloudborneDiagnostics
+
+ !! Called at the end of the timestep after all the columns have been processed to
+ !! to allow additional diagnostics that have been stored in pbuf to be output.
+ !!
+ !! Stub version
+ subroutine CARMAMODEL_OutputDiagnostics(carma, icnst4elem, state, ptend, pbuf, cam_in, rc)
+ use cam_history, only: outfld
+ use constituents, only: cnst_get_ind
+ use camsrfexch, only: cam_in_t
+
+ type(carma_type), intent(in) :: carma !! the carma object
+ integer, intent(in) :: icnst4elem(NELEM, NBIN) !! constituent index for a carma element
+ type(physics_state), intent(in) :: state !! Physics state variables - before CARMA
+ type(physics_ptend), intent(in) :: ptend !! indivdual parameterization tendencies
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:) !! physics buffer
+ type(cam_in_t), intent(in) :: cam_in !! surface inputs
+ integer, intent(out) :: rc !! return code, negative indicates failure
+
+ ! Default return code.
+ rc = RC_OK
+
+ return
+ end subroutine CARMAMODEL_OutputDiagnostics
-end module
+end module carma_model_mod
diff --git a/src/physics/carma/models/tholin/carma_model_mod.F90 b/src/physics/carma/models/tholin/carma_model_mod.F90
index 460971db9d..ac5216f130 100755
--- a/src/physics/carma/models/tholin/carma_model_mod.F90
+++ b/src/physics/carma/models/tholin/carma_model_mod.F90
@@ -102,7 +102,7 @@ subroutine CARMA_DefineModel(carma, rc)
integer, intent(out) :: rc !! return code, negative indicates failure
! Local variables
- real(kind=f) :: RHO_THOLIN = 0.64 ! density of tholin particles (g/cm)
+ real(kind=f) :: RHO_THOLIN = 0.64_f ! density of tholin particles (g/cm)
real(kind=f), parameter :: tholin_rmin = 1.e-7_f ! dust minimum radius (cm)
real(kind=f), parameter :: tholin_vmrat = 2.5_f ! dust volume ratio
@@ -509,7 +509,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
carma_emis_ilev_max = carma_emis_nLevs
do ilev = 1, carma_emis_nLevs
- if (carma_emis_rate(ilev) <= 0.0) then
+ if (carma_emis_rate(ilev) <= 0.0_r8) then
carma_emis_ilev_min = ilev + 1
else
exit
@@ -517,7 +517,7 @@ subroutine CARMA_InitializeModel(carma, lq_carma, rc)
end do
do ilev = carma_emis_nLevs, 1, -1
- if (carma_emis_rate(ilev) <= 0.0) then
+ if (carma_emis_rate(ilev) <= 0.0_r8) then
carma_emis_ilev_max = ilev - 1
else
exit
@@ -639,4 +639,4 @@ subroutine CARMA_WetDeposition(carma, ielem, ibin, sflx, cam_out, state, rc)
return
end subroutine CARMA_WetDeposition
-end module
+end module carma_model_mod
diff --git a/test/system/TR8.sh b/test/system/TR8.sh
index cbdb400463..22ec597f5d 100755
--- a/test/system/TR8.sh
+++ b/test/system/TR8.sh
@@ -10,6 +10,8 @@ ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/cam
rc=$?
ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/camrt
rc=`expr $? + $rc`
+ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/carma
+rc=`expr $? + $rc`
ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/rrtmg -s aer_src
rc=`expr $? + $rc`
ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/components/cam/src/physics/rrtmgp -s data,ext
@@ -27,6 +29,8 @@ ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/cam
rc=$?
ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/camrt
rc=`expr $? + $rc`
+ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/carma
+rc=$?
ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/rrtmg -s aer_src
rc=`expr $? + $rc`
ruby $ADDREALKIND_EXE -r r8 -l 1 -d $CAM_ROOT/src/physics/rrtmgp -s data,ext