1
1
#include " eamxx_cosp.hpp"
2
2
#include " cosp_functions.hpp"
3
3
#include " physics/share/physics_constants.hpp"
4
+ #include " share/util/eamxx_universal_constants.hpp"
4
5
#include " share/property_checks/field_within_interval_check.hpp"
5
6
#include " share/field/field_utils.hpp"
6
7
@@ -65,7 +66,7 @@ void Cosp::set_grids(const std::shared_ptr<const GridsManager> grids_manager)
65
66
add_field<Required>(" surf_radiative_T" , scalar2d , K, grid_name);
66
67
// add_field<Required>("surfelev", scalar2d , m, grid_name);
67
68
// add_field<Required>("landmask", scalar2d , nondim, grid_name);
68
- add_field<Required>(" sunlit " , scalar2d , nondim, grid_name);
69
+ add_field<Required>(" sunlit_mask " , scalar2d , nondim, grid_name);
69
70
add_field<Required>(" p_mid" , scalar3d_mid, Pa, grid_name);
70
71
add_field<Required>(" p_int" , scalar3d_int, Pa, grid_name);
71
72
// add_field<Required>("height_mid", scalar3d_mid, m, grid_name);
@@ -88,11 +89,11 @@ void Cosp::set_grids(const std::shared_ptr<const GridsManager> grids_manager)
88
89
add_field<Required>(" eff_radius_qc" , scalar3d_mid, micron, grid_name);
89
90
add_field<Required>(" eff_radius_qi" , scalar3d_mid, micron, grid_name);
90
91
// Set of fields used strictly as output
92
+ // NOTE we set their corresponding masks in init impl
91
93
add_field<Computed>(" isccp_cldtot" , scalar2d, percent, grid_name);
92
94
add_field<Computed>(" isccp_ctptau" , scalar4d_ctptau, percent, grid_name, 1 );
93
95
add_field<Computed>(" modis_ctptau" , scalar4d_ctptau, percent, grid_name, 1 );
94
96
add_field<Computed>(" misr_cthtau" , scalar4d_cthtau, percent, grid_name, 1 );
95
- add_field<Computed>(" cosp_sunlit" , scalar2d, nondim, grid_name);
96
97
97
98
// We can allocate these now
98
99
m_z_mid = Field (FieldIdentifier (" z_mid" ,scalar3d_mid,m,grid_name));
@@ -107,15 +108,11 @@ void Cosp::initialize_impl (const RunType /* run_type */)
107
108
// Set property checks for fields in this process
108
109
CospFunc::initialize (m_num_cols, m_num_subcols, m_num_levs);
109
110
110
-
111
- // Add note to output files about processing ISCCP fields that are only valid during
112
- // daytime. This can go away once I/O can handle masked time averages.
113
- using stratts_t = std::map<std::string,std::string>;
111
+ // Set the mask field for each of the cosp computed fields
114
112
std::list<std::string> vnames = {" isccp_cldtot" , " isccp_ctptau" , " modis_ctptau" , " misr_cthtau" };
115
- for (const auto field_name : {" isccp_cldtot" , " isccp_ctptau" , " modis_ctptau" , " misr_cthtau" }) {
116
- auto & f = get_field_out (field_name);
117
- auto & atts = f.get_header ().get_extra_data <stratts_t >(" io: string attributes" );
118
- atts[" note" ] = " Night values are zero; divide by cosp_sunlit to get daytime mean" ;
113
+ for (const auto & field_name : vnames) {
114
+ // the mask here is just the sunlit mask, so set it
115
+ get_field_out (field_name).get_header ().set_extra_data (" mask_field" , get_field_in (" sunlit_mask" ));
119
116
}
120
117
}
121
118
@@ -150,7 +147,7 @@ void Cosp::run_impl (const double dt)
150
147
get_field_in (" qv" ).sync_to_host ();
151
148
get_field_in (" qc" ).sync_to_host ();
152
149
get_field_in (" qi" ).sync_to_host ();
153
- get_field_in (" sunlit " ).sync_to_host ();
150
+ get_field_in (" sunlit_mask " ).sync_to_host ();
154
151
get_field_in (" surf_radiative_T" ).sync_to_host ();
155
152
get_field_in (" T_mid" ).sync_to_host ();
156
153
get_field_in (" p_mid" ).sync_to_host ();
@@ -211,7 +208,7 @@ void Cosp::run_impl (const double dt)
211
208
const auto p_mid_h = get_field_in (" p_mid" ).get_view <const Real**,Host>();
212
209
const auto qc_h = get_field_in (" qc" ).get_view <const Real**, Host>();
213
210
const auto qi_h = get_field_in (" qi" ).get_view <const Real**, Host>();
214
- const auto sunlit_h = get_field_in (" sunlit " ).get_view <const Real*, Host>();
211
+ const auto sunlit_h = get_field_in (" sunlit_mask " ).get_view <const Real*, Host>();
215
212
const auto skt_h = get_field_in (" surf_radiative_T" ).get_view <const Real*, Host>();
216
213
const auto p_int_h = get_field_in (" p_int" ).get_view <const Real**, Host>();
217
214
const auto cldfrac_h = get_field_in (" cldfrac_rad" ).get_view <const Real**, Host>();
@@ -223,29 +220,28 @@ void Cosp::run_impl (const double dt)
223
220
auto isccp_cldtot_h = get_field_out (" isccp_cldtot" ).get_view <Real*, Host>();
224
221
auto isccp_ctptau_h = get_field_out (" isccp_ctptau" ).get_view <Real***, Host>();
225
222
auto modis_ctptau_h = get_field_out (" modis_ctptau" ).get_view <Real***, Host>();
226
- auto misr_cthtau_h = get_field_out (" misr_cthtau" ).get_view <Real***, Host>();
227
- auto cosp_sunlit_h = get_field_out (" cosp_sunlit" ).get_view <Real*, Host>(); // Copy of sunlit flag with COSP frequency for proper averaging
223
+ auto misr_cthtau_h = get_field_out (" misr_cthtau" ). get_view<Real***, Host>();
228
224
229
225
Real emsfc_lw = 0.99 ;
230
- Kokkos::deep_copy (cosp_sunlit_h, sunlit_h);
231
226
CospFunc::main (
232
227
m_num_cols, m_num_subcols, m_num_levs, m_num_tau, m_num_ctp, m_num_cth, emsfc_lw,
233
228
sunlit_h, skt_h, T_mid_h, p_mid_h, p_int_h, z_mid_h, qv_h, qc_h, qi_h,
234
229
cldfrac_h, reff_qc_h, reff_qi_h, dtau067_h, dtau105_h,
235
230
isccp_cldtot_h, isccp_ctptau_h, modis_ctptau_h, misr_cthtau_h
236
231
);
237
- // Remask night values to ZERO since our I/O does not know how to handle masked/missing values
238
- // in temporal averages; this is all host data, so we can just use host loops like its the 1980s
232
+ // Mask night values
233
+ constexpr auto fill_value = constants::fill_value<Real>;
239
234
for (int i = 0 ; i < m_num_cols; i++) {
240
235
if (sunlit_h (i) == 0 ) {
241
- isccp_cldtot_h (i) = 0 ;
236
+ // if night, set to fill val
237
+ isccp_cldtot_h (i) = fill_value;
242
238
for (int j = 0 ; j < m_num_tau; j++) {
243
239
for (int k = 0 ; k < m_num_ctp; k++) {
244
- isccp_ctptau_h (i,j,k) = 0 ;
245
- modis_ctptau_h (i,j,k) = 0 ;
240
+ isccp_ctptau_h (i,j,k) = fill_value ;
241
+ modis_ctptau_h (i,j,k) = fill_value ;
246
242
}
247
243
for (int k = 0 ; k < m_num_cth; k++) {
248
- misr_cthtau_h (i,j,k) = 0 ;
244
+ misr_cthtau_h (i,j,k) = fill_value ;
249
245
}
250
246
}
251
247
}
@@ -256,22 +252,6 @@ void Cosp::run_impl (const double dt)
256
252
get_field_out (" isccp_ctptau" ).sync_to_dev ();
257
253
get_field_out (" modis_ctptau" ).sync_to_dev ();
258
254
get_field_out (" misr_cthtau" ).sync_to_dev ();
259
- get_field_out (" cosp_sunlit" ).sync_to_dev ();
260
- } else {
261
- // If not updating COSP statistics, set these to ZERO; this essentially weights
262
- // the ISCCP cloud properties by the sunlit mask. What will be output for time-averages
263
- // then is the time-average mask-weighted statistics; to get true averages, we need to
264
- // divide by the time-average of the mask. I.e., if M is the sunlit mask, and X is the ISCCP
265
- // statistic, then
266
- //
267
- // avg(X) = sum(M * X) / sum(M) = (sum(M * X)/N) / (sum(M)/N) = avg(M * X) / avg(M)
268
- //
269
- // TODO: mask this when/if the AD ever supports masked averages
270
- get_field_out (" isccp_cldtot" ).deep_copy (0 );
271
- get_field_out (" isccp_ctptau" ).deep_copy (0 );
272
- get_field_out (" modis_ctptau" ).deep_copy (0 );
273
- get_field_out (" misr_cthtau" ).deep_copy (0 );
274
- get_field_out (" cosp_sunlit" ).deep_copy (0 );
275
255
}
276
256
}
277
257
0 commit comments