-
Notifications
You must be signed in to change notification settings - Fork 456
EAMxx: fix COSP fill value leak and add dimension coordinates for cosp diagnostics #7992
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
bd476dc
109f33e
745d4b2
ace07b8
f5672ec
beaefe5
25a1e96
7c4165b
36c310a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,7 @@ void Cosp::set_grids(const std::shared_ptr<const GridsManager> grids_manager) | |
| auto micron = micro*m; | ||
| auto m2 = pow(m, 2); | ||
| auto s2 = pow(s, 2); | ||
| auto hPa = hecto*Pa; // hectopascal (100 Pa) | ||
|
|
||
| m_grid = grids_manager->get_grid("physics"); | ||
| const auto& grid_name = m_grid->name(); | ||
|
|
@@ -102,6 +103,130 @@ void Cosp::set_grids(const std::shared_ptr<const GridsManager> grids_manager) | |
| m_z_int = Field(FieldIdentifier("z_int",scalar3d_int,m,grid_name)); | ||
| m_z_mid.allocate_view(); | ||
| m_z_int.allocate_view(); | ||
|
|
||
| // Add COSP dimension coordinate values and bounds as geometry data | ||
| // These are needed for e3sm_diags to produce COSP diagnostics | ||
| using namespace ShortFieldTagsNames; | ||
|
|
||
| // COSP tau bins (optical depth) - standard ISCCP/MODIS bins | ||
| // Bin edges: 0.3, 1.3, 3.6, 9.4, 23, 60, 379 | ||
| if (not m_grid->has_geometry_data("cosp_tau_bnds")) { | ||
| FieldLayout tau_bnds_layout({CMP,CMP},{m_num_tau,2},{"cosp_tau","nbnd"}); | ||
| Field tau_bnds(FieldIdentifier("cosp_tau_bnds", tau_bnds_layout, nondim, grid_name)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could do auto& tau_bnds = m_grid->create_geometry_data("cosp_tau_bnds", tau_bnds_layout,nondim);and avoid to have to create/alloc the field manually, and call
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly for all the other geo data. |
||
| tau_bnds.allocate_view(); | ||
| auto tau_bnds_h = tau_bnds.get_view<Real**,Host>(); | ||
|
|
||
| // Standard ISCCP/MODIS tau bin boundaries | ||
| tau_bnds_h(0,0) = 0.3; tau_bnds_h(0,1) = 1.3; | ||
| tau_bnds_h(1,0) = 1.3; tau_bnds_h(1,1) = 3.6; | ||
| tau_bnds_h(2,0) = 3.6; tau_bnds_h(2,1) = 9.4; | ||
| tau_bnds_h(3,0) = 9.4; tau_bnds_h(3,1) = 23.0; | ||
| tau_bnds_h(4,0) = 23.0; tau_bnds_h(4,1) = 60.0; | ||
| tau_bnds_h(5,0) = 60.0; tau_bnds_h(5,1) = 379.0; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Close but not quite right. These are defined in the COSP source ( |
||
| tau_bnds_h(6,0) = 379.0; tau_bnds_h(6,1) = 100000.0; // effectively infinity | ||
|
|
||
| tau_bnds.sync_to_dev(); | ||
| m_grid->set_geometry_data(tau_bnds); | ||
| } | ||
|
|
||
| // COSP tau centers | ||
| if (not m_grid->has_geometry_data("cosp_tau")) { | ||
| auto tau_bnds = m_grid->get_geometry_data("cosp_tau_bnds"); | ||
| auto tau_bnds_h = tau_bnds.get_view<const Real**,Host>(); | ||
|
|
||
| FieldLayout tau_layout({CMP},{m_num_tau},{"cosp_tau"}); | ||
| Field tau(FieldIdentifier("cosp_tau", tau_layout, nondim, grid_name)); | ||
| tau.allocate_view(); | ||
| auto tau_h = tau.get_view<Real*,Host>(); | ||
|
|
||
| // Geometric mean of bin edges (log-space midpoint) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be better to do here, if it were consistent with what COSP does under the hood, but I think the midpoints are generally expected to have the sort of standard ISCCP-defined midpoints, which are specified explicitly in the above code block I copied. Also note that, unfortunately, the MODIS simulator uses a different set (although it's the same thing just with the first index dropped): |
||
| for (int i=0; i<m_num_tau; ++i) { | ||
| tau_h(i) = std::sqrt(tau_bnds_h(i,0) * tau_bnds_h(i,1)); | ||
| } | ||
|
|
||
| tau.sync_to_dev(); | ||
| m_grid->set_geometry_data(tau); | ||
| } | ||
|
|
||
| // COSP pressure bins (cloud-top pressure in hPa) - standard ISCCP bins | ||
| // Bin edges: 50, 180, 310, 440, 560, 680, 800, 1000 hPa | ||
| if (not m_grid->has_geometry_data("cosp_prs_bnds")) { | ||
| FieldLayout prs_bnds_layout({CMP,CMP},{m_num_ctp,2},{"cosp_prs","nbnd"}); | ||
| Field prs_bnds(FieldIdentifier("cosp_prs_bnds", prs_bnds_layout, hPa, grid_name)); | ||
| prs_bnds.allocate_view(); | ||
| auto prs_bnds_h = prs_bnds.get_view<Real**,Host>(); | ||
|
|
||
| // Standard ISCCP pressure bin boundaries (hPa) | ||
| prs_bnds_h(0,0) = 50.0; prs_bnds_h(0,1) = 180.0; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. close but again differs slightly from what is hard-coded in cosp: |
||
| prs_bnds_h(1,0) = 180.0; prs_bnds_h(1,1) = 310.0; | ||
| prs_bnds_h(2,0) = 310.0; prs_bnds_h(2,1) = 440.0; | ||
| prs_bnds_h(3,0) = 440.0; prs_bnds_h(3,1) = 560.0; | ||
| prs_bnds_h(4,0) = 560.0; prs_bnds_h(4,1) = 680.0; | ||
| prs_bnds_h(5,0) = 680.0; prs_bnds_h(5,1) = 800.0; | ||
| prs_bnds_h(6,0) = 800.0; prs_bnds_h(6,1) = 1000.0; | ||
|
|
||
| prs_bnds.sync_to_dev(); | ||
| m_grid->set_geometry_data(prs_bnds); | ||
| } | ||
|
|
||
| // COSP pressure centers | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that pressure centers are also defined explicitly (hard-coded in COSP) |
||
| if (not m_grid->has_geometry_data("cosp_prs")) { | ||
| auto prs_bnds = m_grid->get_geometry_data("cosp_prs_bnds"); | ||
| auto prs_bnds_h = prs_bnds.get_view<const Real**,Host>(); | ||
|
|
||
| FieldLayout prs_layout({CMP},{m_num_ctp},{"cosp_prs"}); | ||
| Field prs(FieldIdentifier("cosp_prs", prs_layout, hPa, grid_name)); | ||
| prs.allocate_view(); | ||
| auto prs_h = prs.get_view<Real*,Host>(); | ||
|
|
||
| // Midpoint of pressure bins | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think these will come out the same, but they are defined explicitly in the COSP code, we may as well use those here. |
||
| for (int i=0; i<m_num_ctp; ++i) { | ||
| prs_h(i) = (prs_bnds_h(i,0) + prs_bnds_h(i,1)) / 2.0; | ||
| } | ||
|
|
||
| prs.sync_to_dev(); | ||
| m_grid->set_geometry_data(prs); | ||
| } | ||
|
|
||
| // COSP height bins (cloud-top height in m) - standard MISR bins | ||
| // 16 bins from 0 to 20 km | ||
| if (not m_grid->has_geometry_data("cosp_cth_bnds")) { | ||
| FieldLayout cth_bnds_layout({CMP,CMP},{m_num_cth,2},{"cosp_cth","nbnd"}); | ||
| Field cth_bnds(FieldIdentifier("cosp_cth_bnds", cth_bnds_layout, m, grid_name)); | ||
| cth_bnds.allocate_view(); | ||
| auto cth_bnds_h = cth_bnds.get_view<Real**,Host>(); | ||
|
|
||
| // Standard MISR height bin boundaries (m) - 16 bins of varying width | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again there are defined MISR CTH bins, and they differ from what is here: The first, -99 - 0 bin, is a "no retrieval" bin, indicating cases expected to have no cloud top height retrieval (usually because optical depth is too low I think). |
||
| // These follow the CFMIP/COSP standard MISR bins | ||
| const Real cth_edges[17] = {0.0, 500.0, 1000.0, 1500.0, 2000.0, 2500.0, 3000.0, 4000.0, | ||
| 5000.0, 7000.0, 9000.0, 11000.0, 13000.0, 15000.0, 17000.0, 19000.0, 21000.0}; | ||
| for (int i=0; i<m_num_cth; ++i) { | ||
| cth_bnds_h(i,0) = cth_edges[i]; | ||
| cth_bnds_h(i,1) = cth_edges[i+1]; | ||
| } | ||
|
|
||
| cth_bnds.sync_to_dev(); | ||
| m_grid->set_geometry_data(cth_bnds); | ||
| } | ||
|
|
||
| // COSP height centers | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Centers hard-coded in COSP code. See above comments. |
||
| if (not m_grid->has_geometry_data("cosp_cth")) { | ||
| auto cth_bnds = m_grid->get_geometry_data("cosp_cth_bnds"); | ||
| auto cth_bnds_h = cth_bnds.get_view<const Real**,Host>(); | ||
|
|
||
| FieldLayout cth_layout({CMP},{m_num_cth},{"cosp_cth"}); | ||
| Field cth(FieldIdentifier("cosp_cth", cth_layout, m, grid_name)); | ||
| cth.allocate_view(); | ||
| auto cth_h = cth.get_view<Real*,Host>(); | ||
|
|
||
| // Midpoint of height bins | ||
| for (int i=0; i<m_num_cth; ++i) { | ||
| cth_h(i) = (cth_bnds_h(i,0) + cth_bnds_h(i,1)) / 2.0; | ||
| } | ||
|
|
||
| cth.sync_to_dev(); | ||
| m_grid->set_geometry_data(cth); | ||
| } | ||
| } | ||
|
|
||
| // ========================================================================================= | ||
|
|
@@ -115,6 +240,7 @@ void Cosp::initialize_impl (const RunType /* run_type */) | |
| for (const auto& field_name : vnames) { | ||
| // the mask here is just the sunlit mask, so set it | ||
| get_field_out(field_name).get_header().set_extra_data("mask_field", get_field_in("sunlit_mask")); | ||
| get_field_out(field_name).get_header().set_extra_data("mask_value", constants::fill_value<Real>); | ||
| get_field_out(field_name).get_header().set_may_be_filled(true); | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -614,8 +614,6 @@ void RRTMGPRadiation::run_impl (const double dt) { | |
| auto d_dtau105 = get_field_out("dtau105").get_view<Real**>(); | ||
| auto d_sunlit = get_field_out("sunlit_mask").get_view<Real*>(); | ||
|
|
||
| Kokkos::deep_copy(d_dtau067,0.0); | ||
| Kokkos::deep_copy(d_dtau105,0.0); | ||
| // Outputs for AeroCom cloud-top diagnostics | ||
| auto d_T_mid_at_cldtop = get_field_out("T_mid_at_cldtop").get_view<Real *>(); | ||
| auto d_p_mid_at_cldtop = get_field_out("p_mid_at_cldtop").get_view<Real *>(); | ||
|
|
@@ -643,6 +641,12 @@ void RRTMGPRadiation::run_impl (const double dt) { | |
| auto update_rad = scream::rrtmgp::radiation_do(m_rad_freq_in_steps, ts.get_num_steps()); | ||
|
|
||
| if (update_rad) { | ||
| // Init optical depths to zero before recomputing. | ||
| // These fields are only updated on radiation timesteps (controlled by update_rad), | ||
| // and they must be zeroed before accumulation to avoid carrying over stale values. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. meh, i don't believe this, but the bot kept me it is the case
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we don't accum into the fields, and the "fix" is not needed, let's remove it before we merge.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I'm not sure this is right. Fundamentally, we should NOT be calling COSP between radiation calls anyways, and if we do, it looks like zero-ing them out just gives us nonsense anyways. |
||
| // Between radiation calls, these fields persist in the FieldManager so COSP can use them. | ||
| Kokkos::deep_copy(d_dtau067,0.0); | ||
| Kokkos::deep_copy(d_dtau105,0.0); | ||
| // On each chunk, we internally "reset" the GasConcs object to subview the concs 3d array | ||
| // with the correct ncol dimension. So let's keep a copy of the original (ref-counted) | ||
| // array, to restore at the end inside the m_gast_concs object. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -92,6 +92,7 @@ initialize_impl (const RunType /*run_type*/) | |
| Field diag_mask(mask_fid); | ||
| diag_mask.allocate_view(); | ||
| m_diagnostic_output.get_header().set_extra_data("mask_field",diag_mask); | ||
| m_diagnostic_output.get_header().set_extra_data("mask_value", constants::fill_value<Real>); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The extra data
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And we need to clean up the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uh, I do see the extra data |
||
| m_diagnostic_output.get_header().set_may_be_filled(true); | ||
|
|
||
| using stratts_t = std::map<std::string,std::string>; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,12 @@ transfer_extra_data(const scream::Field &src, scream::Field &tgt) | |
| if (src.get_header().may_be_filled()) { | ||
| tgt.get_header().set_may_be_filled(true); | ||
| } | ||
|
|
||
| // Transfer mask_value if present | ||
| if (src.get_header().has_extra_data("mask_value")) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be pointless, since IO does not use |
||
| auto src_mask_value = src.get_header().get_extra_data<scream::Real>("mask_value"); | ||
| tgt.get_header().set_extra_data("mask_value", src_mask_value); | ||
| } | ||
| }; | ||
|
|
||
| // Note: this is also declared in eamxx_scorpio_interface.cpp. Move it somewhere else? | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no idea where the bot came up with these values --- good job bot for either finding the real ones or making up convincing looking ones!