Skip to content
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
66bbc52
Initial (lightly modified) version of tracer_data from CAM; utilities…
jimmielin Oct 9, 2025
92877f7
First try at dechunkization
jimmielin Oct 9, 2025
d523030
First try at removing pbuf support
jimmielin Oct 9, 2025
977910f
Remove (for now) horizontal weighting for aircraft emiss.
jimmielin Oct 14, 2025
88649c6
to_lower units; use state directly in advance_trcdata
jimmielin Oct 14, 2025
322fd79
Merge branch 'development' into hplin/tracer_data
jimmielin Oct 16, 2025
c4b2f17
Fixes to build tracer_data in SIMA.
jimmielin Oct 16, 2025
37064db
Merge branch 'development' into hplin/tracer_data
jimmielin Oct 16, 2025
35c9bbc
Cleanup
jimmielin Oct 21, 2025
4a6bdef
Merge branch 'development' into hplin/tracer_data
jimmielin Oct 24, 2025
d9802ea
Merge branch 'development' into hplin/tracer_data
jimmielin Oct 24, 2025
a8c6b01
Add tracer_data regression test; regridding fix; registry entries for…
jimmielin Oct 31, 2025
1ee957f
Add NaN check in check data
jimmielin Oct 31, 2025
0d683ec
Merge branch 'development' into hplin/tracer_data
jimmielin Dec 29, 2025
3a50f89
Update to sync with review comments atmos_phys (2)
jimmielin Dec 29, 2025
f8381c3
Fix regression tests.
jimmielin Dec 29, 2025
9c1ece0
Fix regression tests, take two
jimmielin Dec 29, 2025
2b9cd4e
Update cime_config/testdefs/testlist_cam.xml
jimmielin Jan 5, 2026
55f06db
Merge branch 'development' into hplin/tracer_data
jimmielin Jan 5, 2026
a49d68e
Merge branch 'hplin/tracer_data' of github.com:jimmielin/CAM-SIMA int…
jimmielin Jan 5, 2026
27f8b9e
Address review comments: reduce extraneous computations in nan calcul…
jimmielin Jan 5, 2026
ffbc6a8
Address review comments: remove unstructured and replace with dycore_…
jimmielin Jan 5, 2026
1c45bfb
Address various review comments in tracer_data
jimmielin Jan 5, 2026
81f93ba
Merge branch 'development' into hplin/tracer_data
jimmielin Jan 5, 2026
c06fe83
Remove duplicate O3
jimmielin Jan 5, 2026
d88de0e
Move string functions to string_core_utils; add pfunit tests
jimmielin Jan 6, 2026
e4d2de0
Address review comments further: errmsg, check_allocate; cleanup
jimmielin Jan 7, 2026
9bbf406
Cleanup for review comments; use statements
jimmielin Jan 8, 2026
7c69f00
Change to allocatables; clean up use statements
jimmielin Jan 12, 2026
0f0dbcf
Cleanup use statements
jimmielin Jan 12, 2026
c4edc59
Use rebin from atmos_phys.
jimmielin Jan 15, 2026
f5e85f6
Merge branch 'development' into hplin/tracer_data
jimmielin Feb 3, 2026
6500043
Merge branch 'development' into hplin/tracer_data
jimmielin Feb 3, 2026
0fbbbda
Merge branch 'development' into hplin/tracer_data
jimmielin Feb 10, 2026
033e390
Merge branch 'development' into hplin/tracer_data
jimmielin Feb 23, 2026
8dcd0e8
Fix check_field_4d with nan_count feature
jimmielin Feb 23, 2026
285fa65
Merge branch 'development' into hplin/tracer_data
jimmielin Mar 7, 2026
319e95f
Small cleanups to tracer_data
jimmielin Mar 9, 2026
775ce6f
Update to latest atmos_phys hash (in main)
jimmielin Mar 9, 2026
d201a47
Fix plat, plon
jimmielin Mar 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions cime_config/testdefs/testlist_cam.xml
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,17 @@
</options>
</test>

<!-- tracer_data chemistry and aerosols input utility test -->
<test compset="FPHYStest" grid="ne3pg3_ne3pg3_mg37" name="SMS_Ln2" testmods="cam/outfrq_trcdata_bam_derecho">
<machines>
<machine name="derecho" compiler="gnu" category="aux_sima"/>
</machines>
<options>
<option name="wallclock">00:10:00</option>
<option name="comment">Test for tracer_data chemistry and aerosols input utilities using prescribed ozone and BAM bulk aerosol input datasets</option>
</options>
</test>

<!-- CAM7 physics tests -->
<test compset="FCAM7" grid="ne3pg3_ne3pg3_mg37" name="SMS_Ln9" testmods="cam/outfrq_se_cslam_analy_ic">
<machines>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
./xmlchange CAM_CONFIG_OPTS="--dyn none --physics-suites tracer_data_test"
./xmlchange RUN_STARTDATE="1979-01-01"
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
! these snapshots were constructed to specifically test whether the data read into the
! physics buffer by tracer_data in CAM will match the data read by CAM-SIMA bit-for-bit.
! this was done by
! (1) taking a FHIST_C4 snapshot (which has prescribed_ozone and aero)
! in this case a ne3pg3_fhistc4_gw_drag_cam4_oro snapshot,
! (2) using nco to zero out the prescribed ozone and aero fields from the snapshot data,
! to create the "before" snapshot.
! (3) the "after" snapshot is the original snapshot file (which has non-zero values for prescribed
! ozone and aerosols)
! the test will pass iff. the tracer_data utility in CAM-SIMA and the prescribed_ozone/aerosols schemes
! can populate the prescribed fields bit-for-bit compared to the original snapshot file.

ncdata = '/glade/campaign/cesm/community/amwg/sima_baselines/cam_sima_test_snapshots/cam_ne3pg3_fhistc4_tracer_data_0xprescribed-ozone-aero_from_cam4_oro_snapshot_derecho_gnu_after_c20251028.nc'
ncdata_check = '/glade/campaign/cesm/community/amwg/sima_baselines/cam_sima_test_snapshots/cam_ne3pg3_fhistc4_gw_drag_cam4_oro_snapshot_derecho_gnu_after_c20250826.nc'

! tolerances for testing
ncdata_check_err = .true.
min_difference = 2e-15

! cam4 vertical levels (FHIST_C4 snapshots)
pver = 26

prescribed_aero_datapath = "/glade/campaign/cesm/cesmdata/inputdata/atm/cam/chem/trop_mozart_aero/aero"
prescribed_aero_file = "aero_1.9x2.5_L26_1850-2005_c091112.nc"
prescribed_aero_filelist = "aero_1.9x2.5_L26_list_c070514.txt"
prescribed_aero_model = "bulk"
prescribed_aero_specifier = 'sulf:SO4', 'bcar1:CB1', 'bcar2:CB2', 'ocar1:OC1', 'ocar2:OC2', 'sslt1:SSLT01', 'sslt2:SSLT02', 'sslt3:SSLT03', 'sslt4:SSLT04', 'dust1:DST01', 'dust2:DST02', 'dust3:DST03', 'dust4:DST04'
prescribed_aero_type = "INTERP_MISSING_MONTHS"
prescribed_aero_cycle_yr = 0
prescribed_aero_fixed_tod = 0
prescribed_aero_fixed_ymd = 0

aerodep_flx_datapath = '/glade/campaign/cesm/cesmdata/inputdata/atm/cam/chem/trop_mozart_aero/aero'
aerodep_flx_file = 'aerosoldep_monthly_1849-2006_1.9x2.5_c090803.nc'
aerodep_flx_specifier = 'BCDEPWET', 'BCPHODRY', 'BCPHIDRY', 'OCDEPWET', 'OCPHODRY', 'OCPHIDRY', 'DSTX01DD', 'DSTX02DD', 'DSTX03DD',
'DSTX04DD', 'DSTX01WD', 'DSTX02WD', 'DSTX03WD', 'DSTX04WD'
aerodep_flx_type = 'INTERP_MISSING_MONTHS'
aerodep_flx_cycle_yr = 0

prescribed_ozone_datapath = "/glade/campaign/cesm/cesmdata/inputdata/atm/cam/ozone"
prescribed_ozone_file = "ozone_1.9x2.5_L26_1850-2005_c091112.nc"
prescribed_ozone_filelist = "UNSET"
prescribed_ozone_name = "O3"
prescribed_ozone_type = "INTERP_MISSING_MONTHS"
prescribed_ozone_fixed_tod = 0
prescribed_ozone_fixed_ymd = 0
prescribed_ozone_cycle_yr = 0

hist_output_frequency;h1: 1*nsteps
hist_max_frames;h1: 1
hist_add_inst_fields;h1:ozone
hist_add_inst_fields;h1:sulf_D,bcar1_D,bcar2_D,ocar1_D,ocar2_D,sslt1_D,sslt2_D,sslt3_D,sslt4_D,dust1_D,dust2_D,dust3_D,dust4_D
hist_precision;h1: REAL64
111 changes: 111 additions & 0 deletions src/core_utils/string_core_utils.F90
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ module string_core_utils
public :: split ! Parse a string into tokens, one at a time
public :: stringify ! Convert one or more values of any intrinsic data types to a character string for pretty printing
public :: tokenize ! Parse a string into tokens
public :: increment_string ! Increment a string whose ending characters are digits.
public :: last_non_digit ! Get position of last non-digit in the input string.
public :: get_last_significant_char ! Get position of last significant (non-blank, non-null) character in string.

interface tokenize
module procedure tokenize_into_first_last
Expand Down Expand Up @@ -287,4 +290,112 @@ pure subroutine tokenize_into_tokens_separator(string, set, tokens, separator)
end if
end subroutine tokenize_into_tokens_separator

! Increment a string whose ending characters are digits.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we actually use this feature in cam. This was left over from the old MOZART chemical transport model. Not sure that increment_string needs to migrated to CAM-SIMA.

Copy link
Member Author

Choose a reason for hiding this comment

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

It seems it's mentioned in this "ccm type filename" block in tracer_data.

if ((.not. present(filenames_list)) .or. (len_trim(filenames_list) == 0)) then
!-----------------------------------------------------------------------
! ... ccm type filename
!-----------------------------------------------------------------------
pos = len_trim(filename)
fn_new = filename(:pos)
if (masterproc) write (iulog, *) sub//': old filename = ', trim(fn_new)
if (fn_new(pos - 2:) == '.nc') then
pos = pos - 3
end if
istat = increment_string(fn_new(:pos), 1)
if (istat /= 0) then
write (iulog, *) sub//': increment_string returned ', istat
write (iulog, *) ' while trying to decrement ', trim(fn_new)
call endrun(sub//': increment_string failure')
end if

I agree it is likely unused. I am happy to make an issue to remove this in a future cleanup. Thanks!

Copy link
Collaborator

Choose a reason for hiding this comment

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

It would be nice to clean this up. If you want to do it an a future PR, that's fine with me.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks @fvitt - I added #474 as a future issue so I can go back and clean this up.

! The incremented integer must be in the range [0 - (10**n)-1]
! where n is the number of trailing digits.
! Return values:
!
! 0 success
! -1 error: no trailing digits in string
! -2 error: incremented integer is out of range
integer function increment_string(s, inc)
integer, intent(in) :: inc ! value to increment string (may be negative)
character(len=*), intent(inout) :: s ! string with trailing digits

integer :: &
i, & ! index
lstr, & ! number of significant characters in string
lnd, & ! position of last non-digit
ndigit, & ! number of trailing digits
ival, & ! integer value of trailing digits
pow, & ! power of ten
digit ! integer value of a single digit

lstr = get_last_significant_char(s)
lnd = last_non_digit(s)
ndigit = lstr - lnd

if(ndigit == 0) then
increment_string = -1
return
end if

! Calculate integer corresponding to trailing digits.
ival = 0
pow = 0
do i = lstr,lnd+1,-1
digit = ICHAR(s(i:i)) - ICHAR('0')
ival = ival + digit * 10**pow
pow = pow + 1
end do

! Increment the integer
ival = ival + inc
if( ival < 0 .or. ival > 10**ndigit-1 ) then
increment_string = -2
return
end if

! Overwrite trailing digits
pow = ndigit
do i = lnd+1,lstr
digit = MOD( ival,10**pow ) / 10**(pow-1)
s(i:i) = CHAR( ICHAR('0') + digit )
pow = pow - 1
end do

increment_string = 0

end function increment_string

! Get position of last non-digit in the input string.
! Return values:
! > 0 => position of last non-digit
! = 0 => token is all digits (or empty)
integer pure function last_non_digit(s)
character(len=*), intent(in) :: s
integer :: n, nn, digit

n = get_last_significant_char(s)
if(n == 0) then ! empty string
last_non_digit = 0
return
end if

do nn = n,1,-1
digit = ICHAR(s(nn:nn)) - ICHAR('0')
if( digit < 0 .or. digit > 9 ) then
last_non_digit = nn
return
end if
end do

last_non_digit = 0 ! all characters are digits

end function last_non_digit

! Get position of last significant character in string.
! Here significant means non-blank or non-null.
! Return values:
! > 0 => position of last significant character
! = 0 => no significant characters in string
integer pure function get_last_significant_char(cs)
character(len=*), intent(in) :: cs ! Input character string
integer :: l, n

l = LEN(cs)
if( l == 0 ) then
get_last_significant_char = 0
return
end if

do n = l,1,-1
if( cs(n:n) /= ' ' .and. cs(n:n) /= CHAR(0) ) then
exit
end if
end do
get_last_significant_char = n

end function get_last_significant_char

end module string_core_utils
80 changes: 80 additions & 0 deletions src/data/registry.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1627,6 +1627,86 @@
<ic_file_input_names>pbuf_clubbtop</ic_file_input_names>
</variable>

<!-- Test for tracer_data / aerosols / BAM -->
<variable local_name="sulf"
standard_name="sulf"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>sulf pbuf_sulf cnst_sulf </ic_file_input_names>
</variable>
<variable local_name="bcar1"
standard_name="bcar1"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>bcar1 pbuf_bcar1 cnst_bcar1</ic_file_input_names>
</variable>
<variable local_name="bcar2"
standard_name="bcar2"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>bcar2 pbuf_bcar2 cnst_bcar2</ic_file_input_names>
</variable>
<variable local_name="ocar1"
standard_name="ocar1"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>ocar1 pbuf_ocar1 cnst_ocar1</ic_file_input_names>
</variable>
<variable local_name="ocar2"
standard_name="ocar2"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>ocar2 pbuf_ocar2 cnst_ocar2</ic_file_input_names>
</variable>
<variable local_name="sslt1"
standard_name="sslt1"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>sslt1 pbuf_sslt1 cnst_sslt1</ic_file_input_names>
</variable>
<variable local_name="sslt2"
standard_name="sslt2"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>sslt2 pbuf_sslt2 cnst_sslt2</ic_file_input_names>
</variable>
<variable local_name="sslt3"
standard_name="sslt3"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>sslt3 pbuf_sslt3 cnst_sslt3</ic_file_input_names>
</variable>
<variable local_name="sslt4"
standard_name="sslt4"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>sslt4 pbuf_sslt4 cnst_sslt4</ic_file_input_names>
</variable>
<variable local_name="dust1"
standard_name="dust1"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>dust1 pbuf_dust1 cnst_dust1</ic_file_input_names>
</variable>
<variable local_name="dust2"
standard_name="dust2"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>dust2 pbuf_dust2 cnst_dust2</ic_file_input_names>
</variable>
<variable local_name="dust3"
standard_name="dust3"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>dust3 pbuf_dust3 cnst_dust3</ic_file_input_names>
</variable>
<variable local_name="dust4"
standard_name="dust4"
units="kg kg-1" type="real" constituent="true">
<dimensions>horizontal_dimension vertical_layer_dimension</dimensions>
<ic_file_input_names>dust4 pbuf_dust4 cnst_dust4</ic_file_input_names>
</variable>

<!-- Zhang McFarlane (ZM) Variables -->
<variable local_name="ql"
standard_name="in_cloud_water_vapor_mixing_ratio_wrt_moist_air_and_condensed_water_due_to_deep_convection"
Expand Down
Loading