diff --git a/src/mam4xx/aero_model.hpp b/src/mam4xx/aero_model.hpp index 456e233f7..a636902ae 100644 --- a/src/mam4xx/aero_model.hpp +++ b/src/mam4xx/aero_model.hpp @@ -29,6 +29,8 @@ const int naerosvmax = 51; // maximum bin number for aerosol const int maxd_aspectype = 14; constexpr int pcnst = mam4::pcnst; +using View1D = DeviceType::view_1d; +using ConstView1D = DeviceType::view_1d; using View2D = DeviceType::view_2d; using View2DHost = typename HostType::view_2d; @@ -804,9 +806,10 @@ void index_ordering(const int lspec, const int imode, const int lphase, int &mm, // ============================================================================= KOKKOS_INLINE_FUNCTION -int examine_prec_exist(const int level_for_precipitation, const Real pdel[], - const Real prain[], const Real cmfdqr[], - const Real evapr[]) { +int examine_prec_exist(const int level_for_precipitation, + haero::ConstColumnView pdel, + haero::ConstColumnView prain, const View1D &cmfdqr, + const ConstView1D &evapr) { // clang-format off // ---------------------------------------------------------------------- // examine if level level_for_precipitation has precipitation. @@ -881,10 +884,11 @@ void set_f_act_coarse(const int kk, } // ============================================================================= -KOKKOS_INLINE_FUNCTION -void calc_resusp_to_coarse(const int mm, const bool update_dqdt, - const Real rcscavt, const Real rsscavt, - Real &dqdt_tmp, Real rtscavt_sv[]) { +template +KOKKOS_INLINE_FUNCTION void +calc_resusp_to_coarse(const int mm, const bool update_dqdt, const Real rcscavt, + const Real rsscavt, Real &dqdt_tmp, + const VectorType &rtscavt_sv) { // clang-format off //----------------------------------------------------------------------- // resuspension goes to coarse mode diff --git a/src/mam4xx/modal_aer_opt.hpp b/src/mam4xx/modal_aer_opt.hpp index b128f78c0..2ba29d6af 100644 --- a/src/mam4xx/modal_aer_opt.hpp +++ b/src/mam4xx/modal_aer_opt.hpp @@ -407,10 +407,10 @@ also output wetvol and watervol refi = haero::abs(crefin.imag()); } // calc_refin_complex - -KOKKOS_INLINE_FUNCTION -void compute_factors(const int prefri, const Real ref_ind, - const Real *ref_table, int &ix, Real &tt) { +template +KOKKOS_INLINE_FUNCTION void +compute_factors(const int prefri, const Real ref_ind, + const VectorType &ref_table, int &ix, Real &tt) { // Compute factors for the real or imaginary parts // prefri, ncol @@ -457,11 +457,12 @@ void compute_factors(const int prefri, const Real ref_ind, } // compute_factors -KOKKOS_INLINE_FUNCTION -void binterp(const View3D &table, const Real ref_real, const Real ref_img, - const Real ref_real_tab[prefr], const Real ref_img_tab[prefi], - int &itab, int &jtab, Real &ttab, Real &utab, Real coef[ncoef], - const int itab_1) { +template +KOKKOS_INLINE_FUNCTION void +binterp(const View3D &table, const Real ref_real, const Real ref_img, + const VectorType &ref_real_tab, const VectorType &ref_img_tab, + int &itab, int &jtab, Real &ttab, Real &utab, Real coef[ncoef], + const int itab_1) { /*------------------------------------------------------------------------------ Bilinear interpolation along the refractive index dimensions of the table to estimate Chebyshev coefficients at an @@ -685,18 +686,18 @@ KOKKOS_INLINE_FUNCTION void modal_aero_sw_wo_diagnostics_k( casm[ncoef] = {}; // coefficient for extinction, absoption, and // asymmetry [unitless] - binterp(sub_extpsw, refr, refi, ref_real_tab.data(), ref_img_tab.data(), - itab, jtab, ttab, utab, cext, itab_1); + binterp(sub_extpsw, refr, refi, ref_real_tab, ref_img_tab, itab, jtab, + ttab, utab, cext, itab_1); const auto sub_abspsw = aersol_optics_data.abspsw[mm][isw]; - binterp(sub_abspsw, refr, refi, ref_real_tab.data(), ref_img_tab.data(), - itab, jtab, ttab, utab, cabs, itab_1); + binterp(sub_abspsw, refr, refi, ref_real_tab, ref_img_tab, itab, jtab, + ttab, utab, cabs, itab_1); const auto sub_asmpsw = aersol_optics_data.asmpsw[mm][isw]; - binterp(sub_asmpsw, refr, refi, ref_real_tab.data(), ref_img_tab.data(), - itab, jtab, ttab, utab, casm, itab_1); + binterp(sub_asmpsw, refr, refi, ref_real_tab, ref_img_tab, itab, jtab, + ttab, utab, casm, itab_1); // parameterized optical properties Real pext = zero; // parameterized specific extinction [m2/kg] @@ -956,9 +957,8 @@ KOKKOS_INLINE_FUNCTION void modal_aero_lw_k( int jtab = zero; Real ttab, utab = {}; Real cabs[ncoef] = {}; - binterp(aersol_optics_data.absplw[mm][ilw], refr, refi, - ref_real_tab.data(), ref_img_tab.data(), itab, jtab, ttab, utab, - cabs, itab_1); + binterp(aersol_optics_data.absplw[mm][ilw], refr, refi, ref_real_tab, + ref_img_tab, itab, jtab, ttab, utab, cabs, itab_1); // parameterized optical properties Real pabs = zero; // parameterized specific extinction [m2/kg] diff --git a/src/mam4xx/wet_dep.hpp b/src/mam4xx/wet_dep.hpp index c8e3568e3..2fb890e6f 100644 --- a/src/mam4xx/wet_dep.hpp +++ b/src/mam4xx/wet_dep.hpp @@ -113,10 +113,10 @@ inline void init_scavimptbl(View2DHost scavimptblvol, * */ // clang-format on -template +template KOKKOS_INLINE_FUNCTION void -calculate_cloudy_volume(const int nlev, const Real cld[/*nlev*/], FUNC lprec, - const bool is_tot_cld, Real cldv[/*nlev*/]) { +calculate_cloudy_volume(const int nlev, const VectorType &cld, FUNC lprec, + const bool is_tot_cld, const View1D &cldv) { // BAD CONSTANT const Real small_value_30 = 1.e-30; const Real small_value_36 = 1.e-36; @@ -1134,12 +1134,15 @@ void wetdepa_v2(const Real deltat, const Real pdel, const Real cmfdqr, * * @pre atm is initialized correctly and has the correct number of levels. */ + KOKKOS_INLINE_FUNCTION -void clddiag(const int nlev, const Real *temperature, const Real *pmid, - const Real *pdel, const Real *cmfdqr, const Real *evapc, - const Real *cldt, const Real *cldcu, const Real *cldst, - const Real *evapr, const Real *prain, Real *cldv, Real *cldvcu, - Real *cldvst, Real *rain) { +void clddiag(const int nlev, haero::ConstColumnView temperature, + haero::ConstColumnView pmid, haero::ConstColumnView pdel, + const View1D &cmfdqr, const View1D &evapc, + const haero::ConstColumnView &cldt, const View1D &cldcu, + const View1D &cldst, const haero::ConstColumnView &evapr, + const haero::ConstColumnView &prain, const View1D &cldv, + const View1D &cldvcu, const View1D &cldvst, const View1D &rain) { // Calculate local precipitation production rate // In src/chemistry/aerosol/wetdep.F90, (prain + cmfdqr) is used for // source_term @@ -1228,27 +1231,23 @@ void cloud_diagnostics(const ThreadTeam &team, // NOTE: The k loop inside clddiag cannot be converted to parallel_for // because precabs requires values from the previous elevation (k-1). Kokkos::single(Kokkos::PerTeam(team), [=]() { - wetdep::clddiag(nlev, temperature.data(), pmid.data(), pdel.data(), - cmfdqr.data(), evapc.data(), cldt.data(), cldcu.data(), - cldst.data(), evapr.data(), prain.data(), + wetdep::clddiag(nlev, temperature, pmid, pdel, cmfdqr, evapc, cldt, cldcu, + cldst, evapr, prain, // outputs - cldv.data(), cldvcu.data(), cldvst.data(), rain.data()); + cldv, cldvcu, cldvst, rain); }); } - -KOKKOS_INLINE_FUNCTION -void set_f_act(const ThreadTeam &team, int *isprx, - const View1D &f_act_conv_coarse, - const View1D &f_act_conv_coarse_dust, - const View1D &f_act_conv_coarse_nacl, - haero::ConstColumnView pdel, haero::ConstColumnView prain, - const View1D &cmfdqr, const ConstView1D &evapr, - const View2D &state_q, const View2D &ptend_q, const Real dt, - const int nlev) { +template +KOKKOS_INLINE_FUNCTION void +set_f_act(const ThreadTeam &team, VectorIntType &isprx, + const View1D &f_act_conv_coarse, const View1D &f_act_conv_coarse_dust, + const View1D &f_act_conv_coarse_nacl, haero::ConstColumnView pdel, + haero::ConstColumnView prain, const View1D &cmfdqr, + const ConstView1D &evapr, const View2D &state_q, + const View2D &ptend_q, const Real dt, const int nlev) { Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev), [&](int k) { - isprx[k] = aero_model::examine_prec_exist(k, pdel.data(), prain.data(), - cmfdqr.data(), evapr.data()); + isprx[k] = aero_model::examine_prec_exist(k, pdel, prain, cmfdqr, evapr); aero_model::set_f_act_coarse(k, state_q, ptend_q, dt, f_act_conv_coarse[k], f_act_conv_coarse_dust[k], @@ -1257,13 +1256,12 @@ void set_f_act(const ThreadTeam &team, int *isprx, } // Computes lookup table for aerosol impaction/interception scavenging rates -KOKKOS_INLINE_FUNCTION -void modal_aero_bcscavcoef_get(const ThreadTeam &team, const Diagnostics &diags, - const int *isprx, const View2D &scavimptblvol, - const View2D &scavimptblnum, - const View1D &scavcoefnum, - const View1D &scavcoefvol, const int imode, - const int nlev) { +template +KOKKOS_INLINE_FUNCTION void modal_aero_bcscavcoef_get( + const ThreadTeam &team, const Diagnostics &diags, + const VectorIntType &isprx, const View2D &scavimptblvol, + const View2D &scavimptblnum, const View1D &scavcoefnum, + const View1D &scavcoefvol, const int imode, const int nlev) { Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev), [&](int k) { scavcoefnum[k] = scavcoefvol[k] = 0; const bool let_it_rain = (isprx[k] == 1); @@ -1279,14 +1277,12 @@ void modal_aero_bcscavcoef_get(const ThreadTeam &team, const Diagnostics &diags, } // Computes lookup table for aerosol impaction/interception scavenging rates -KOKKOS_INLINE_FUNCTION -void modal_aero_bcscavcoef_get(const ThreadTeam &team, - const View2D &wet_geometric_mean_diameter_i, - const int *isprx, const View2D &scavimptblvol, - const View2D &scavimptblnum, - const View1D &scavcoefnum, - const View1D &scavcoefvol, const int imode, - const int nlev) { +template +KOKKOS_INLINE_FUNCTION void modal_aero_bcscavcoef_get( + const ThreadTeam &team, const View2D &wet_geometric_mean_diameter_i, + const VectorIntType &isprx, const View2D &scavimptblvol, + const View2D &scavimptblnum, const View1D &scavcoefnum, + const View1D &scavcoefvol, const int imode, const int nlev) { Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev), [&](int k) { scavcoefnum[k] = scavcoefvol[k] = 0; const bool let_it_rain = (isprx[k] == 1); @@ -1318,10 +1314,9 @@ void define_act_frac(const ThreadTeam &team, const View1D &sol_facti, sol_factic[k], sol_factb[k], f_act_conv[k]); }); } - -KOKKOS_INLINE_FUNCTION -void compute_q_tendencies_phase_1( - Real &scavt, Real &bcscavt, Real &rcscavt, Real rtscavt_sv[], +template +KOKKOS_INLINE_FUNCTION void compute_q_tendencies_phase_1( + Real &scavt, Real &bcscavt, Real &rcscavt, const VectorType &rtscavt_sv, const Real f_act_conv, const Real scavcoefnum, const Real scavcoefvol, const Real totcond, const Real cmfdqr, const Real conicw, const Real evapc, const Real evapr, const Real prain, const Real dlf, const Real cldt, @@ -1361,10 +1356,9 @@ void compute_q_tendencies_phase_1( aero_model::calc_resusp_to_coarse(mm, update_dqdt, rcscavt, rsscavt, scavt, rtscavt_sv); } - -KOKKOS_INLINE_FUNCTION -void compute_q_tendencies_phase_2( - Real &scavt, Real &bcscavt, Real &rcscavt, Real rtscavt_sv[], +template +KOKKOS_INLINE_FUNCTION void compute_q_tendencies_phase_2( + Real &scavt, Real &bcscavt, Real &rcscavt, const VectorType &rtscavt_sv, const Real qqcw_tmp, const Real tracer, // const Prognostics &progs, @@ -1501,7 +1495,7 @@ void compute_q_tendencies( // "most current" q compute_q_tendencies_phase_1( // These are the output values - scavt[k], bcscavt[k], rcscavt[k], rtscavt_sv_k.data(), + scavt[k], bcscavt[k], rcscavt[k], rtscavt_sv_k, // The rest of the values are input only. f_act_conv[k], scavcoefnum[k], scavcoefvol[k], totcond[k], cmfdqr[k], conicw[k], evapc[k], evapr[k], prain[k], dlf[k], cldt[k], @@ -1524,7 +1518,7 @@ void compute_q_tendencies( const Real qqcw_tmp = 0.0; compute_q_tendencies_phase_2( // These are the output values - scavt[k], bcscavt[k], rcscavt[k], rtscavt_sv_k.data(), qqcw_tmp, + scavt[k], bcscavt[k], rcscavt[k], rtscavt_sv_k, qqcw_tmp, qqcw(k, mm), // The rest of the values are input only. // progs, @@ -1848,8 +1842,8 @@ void aero_model_wetdep( mam4::water_uptake::modal_aero_water_uptake_dr( // inputs calcsizedata.nspec_amode, calcsizedata.specdens_amode, - calcsizedata.spechygro, calcsizedata.lspectype_amode, - state_q_kk.data(), temperature(kk), pmid(kk), cldt(kk), dgnumdry_m_kk, + calcsizedata.spechygro, calcsizedata.lspectype_amode, state_q_kk, + temperature(kk), pmid(kk), cldt(kk), dgnumdry_m_kk, // outputs dgnumwet_m_kk, qaerwat_m_kk, wetdens_kk); } @@ -1930,7 +1924,7 @@ void aero_model_wetdep( // input team, // outputs - isprx.data(), f_act_conv_coarse, f_act_conv_coarse_dust, + isprx, f_act_conv_coarse, f_act_conv_coarse_dust, f_act_conv_coarse_nacl, // inputs pdel, prain, cmfdqr, evapr, state_q, ptend_q, dt, nlev); @@ -1958,7 +1952,7 @@ void aero_model_wetdep( // rates wetdep::modal_aero_bcscavcoef_get( // inputs - team, wet_geometric_mean_diameter_i, isprx.data(), scavimptblvol, + team, wet_geometric_mean_diameter_i, isprx, scavimptblvol, scavimptblnum, // outputs scavcoefnum, scavcoefvol, @@ -2084,9 +2078,9 @@ void aero_model_wetdep( const auto ptend_q_kk = ekat::subview(ptend_q, kk); const auto state_q_kk = ekat::subview(state_q, kk); const auto qqcw_kk = ekat::subview(qqcw, kk); - utils::inject_qqcw_to_prognostics(qqcw_kk.data(), progs, kk); - utils::inject_stateq_to_prognostics(state_q_kk.data(), progs, kk); - utils::inject_ptend_to_tendencies(ptend_q_kk.data(), tends, kk); + utils::inject_qqcw_to_prognostics(qqcw_kk, progs, kk); + utils::inject_stateq_to_prognostics(state_q_kk, progs, kk); + utils::inject_ptend_to_tendencies(ptend_q_kk, tends, kk); }); team.team_barrier(); diff --git a/src/tests/mam4_wet_deposition_unit_tests.cpp b/src/tests/mam4_wet_deposition_unit_tests.cpp index 9c835daec..d8c9ca7ef 100644 --- a/src/tests/mam4_wet_deposition_unit_tests.cpp +++ b/src/tests/mam4_wet_deposition_unit_tests.cpp @@ -202,17 +202,10 @@ TEST_CASE("test_calculate_cloudy_volume", "mam4_wet_deposition_process") { Kokkos::parallel_for( "test_calculate_cloudy_volume_true", 1, KOKKOS_LAMBDA(const int) { - Real *cld_device = cld.data(); - Real *lprec_device = lprec.data(); - Real *cldv_device = cldv.data(); - Real *sumppr_all_device = sumppr_all.data(); - // True is the only flag with validation data available - auto lprec = [&](int i) { return lprec_device[i]; }; - mam4::wetdep::calculate_cloudy_volume(nlev, cld_device, lprec, true, - cldv_device); - sumppr_all_device[0] = lprec_device[0]; + mam4::wetdep::calculate_cloudy_volume(nlev, cld, lprec, true, cldv); + sumppr_all[0] = lprec[0]; for (int i = 1; i < nlev; i++) - sumppr_all_device[i] = sumppr_all_device[i - 1] + lprec_device[i]; + sumppr_all[i] = sumppr_all[i - 1] + lprec[i]; }); auto cld_view = Kokkos::create_mirror_view(cld); diff --git a/src/validation/wetdep/calculate_cloudy_volume.cpp b/src/validation/wetdep/calculate_cloudy_volume.cpp index 6c64c08c0..b2366c62f 100644 --- a/src/validation/wetdep/calculate_cloudy_volume.cpp +++ b/src/validation/wetdep/calculate_cloudy_volume.cpp @@ -56,8 +56,8 @@ void test_calculate_cloudy_volume_process(const Input &input, Output &output) { Kokkos::parallel_for( "wetdep::calculate_cloudy_volume", 1, KOKKOS_LAMBDA(const int) { auto lprec = [&](int i) { return lprec_dev[i]; }; - mam4::wetdep::calculate_cloudy_volume(nlev, cld_dev.data(), lprec, - is_tot_cld, cldv_dev.data()); + mam4::wetdep::calculate_cloudy_volume(nlev, cld_dev, lprec, is_tot_cld, + cldv_dev); sumppr_all_dev[0] = lprec_dev[0]; for (int i = 1; i < nlev; i++) diff --git a/src/validation/wetdep/wetdep_clddiag.cpp b/src/validation/wetdep/wetdep_clddiag.cpp index 57df113a8..b521f4eaf 100644 --- a/src/validation/wetdep/wetdep_clddiag.cpp +++ b/src/validation/wetdep/wetdep_clddiag.cpp @@ -69,32 +69,58 @@ void test_wetdep_clddiag_process(const Input &input, Output &output) { EKAT_ASSERT(evapr.size() == pver); EKAT_ASSERT(prain.size() == pver); - // Create Real arrays for inputs - // std::vectors can't be copied directly to device memory by Kokkos - // Maybe this should be a unique_ptr.. - // Since pver is actually hard coded, maybe this isn't necessary - Real temperature_arr[pver]; - Real pmid_arr[pver]; - Real pdel_arr[pver]; - Real cmfdqr_arr[pver]; - Real evapc_arr[pver]; - Real cldt_arr[pver]; - Real cldcu_arr[pver]; - Real cldst_arr[pver]; - Real evapr_arr[pver]; - Real prain_arr[pver]; - - // Use std::copy to copy input arrays to Real arrays - std::copy(temperature.begin(), temperature.end(), temperature_arr); - std::copy(pmid.begin(), pmid.end(), pmid_arr); - std::copy(pdel.begin(), pdel.end(), pdel_arr); - std::copy(cmfdqr.begin(), cmfdqr.end(), cmfdqr_arr); - std::copy(evapc.begin(), evapc.end(), evapc_arr); - std::copy(cldt.begin(), cldt.end(), cldt_arr); - std::copy(cldcu.begin(), cldcu.end(), cldcu_arr); - std::copy(cldst.begin(), cldst.end(), cldst_arr); - std::copy(evapr.begin(), evapr.end(), evapr_arr); - std::copy(prain.begin(), prain.end(), prain_arr); + using View1DHost = typename HostType::view_1d; + using View1D = typename DeviceType::view_1d; + + // For temperature + View1DHost temperature_host((Real *)temperature.data(), pver); + View1D temperature_arr("temperature", pver); + Kokkos::deep_copy(temperature_arr, temperature_host); + + // For pmid + View1DHost pmid_host((Real *)pmid.data(), pver); + View1D pmid_arr("pmid", pver); + Kokkos::deep_copy(pmid_arr, pmid_host); + + // For pdel + View1DHost pdel_host((Real *)pdel.data(), pver); + View1D pdel_arr("pdel", pver); + Kokkos::deep_copy(pdel_arr, pdel_host); + + // For cmfdqr + View1DHost cmfdqr_host((Real *)cmfdqr.data(), pver); + View1D cmfdqr_arr("cmfdqr", pver); + Kokkos::deep_copy(cmfdqr_arr, cmfdqr_host); + + // For evapc + View1DHost evapc_host((Real *)evapc.data(), pver); + View1D evapc_arr("evapc", pver); + Kokkos::deep_copy(evapc_arr, evapc_host); + + // For cldt + View1DHost cldt_host((Real *)cldt.data(), pver); + View1D cldt_arr("cldt", pver); + Kokkos::deep_copy(cldt_arr, cldt_host); + + // For cldcu + View1DHost cldcu_host((Real *)cldcu.data(), pver); + View1D cldcu_arr("cldcu", pver); + Kokkos::deep_copy(cldcu_arr, cldcu_host); + + // For cldst + View1DHost cldst_host((Real *)cldst.data(), pver); + View1D cldst_arr("cldst", pver); + Kokkos::deep_copy(cldst_arr, cldst_host); + + // For evapr + View1DHost evapr_host((Real *)evapr.data(), pver); + View1D evapr_arr("evapr", pver); + Kokkos::deep_copy(evapr_arr, evapr_host); + + // For prain + View1DHost prain_host((Real *)prain.data(), pver); + View1D prain_arr("prain", pver); + Kokkos::deep_copy(prain_arr, prain_host); // Prepare device views for output arrays ColumnView cldv_dev = mam4::validation::create_column_view(pver); @@ -102,26 +128,13 @@ void test_wetdep_clddiag_process(const Input &input, Output &output) { ColumnView cldvst_dev = mam4::validation::create_column_view(pver); ColumnView rain_dev = mam4::validation::create_column_view(pver); + // TODO: let's use team policy Kokkos::parallel_for( "wetdep::clddiag", 1, KOKKOS_LAMBDA(const int) { - // On device, create Real arrays for outputs - Real cldv[pver]; - Real cldvcu[pver]; - Real cldvst[pver]; - Real rain[pver]; - mam4::wetdep::clddiag(pver, temperature_arr, pmid_arr, pdel_arr, cmfdqr_arr, evapc_arr, cldt_arr, cldcu_arr, - cldst_arr, evapr_arr, prain_arr, cldv, cldvcu, - cldvst, rain); - - // Copy values back to host - for (size_t i = 0; i < pver; ++i) { - cldv_dev(i) = cldv[i]; - cldvcu_dev(i) = cldvcu[i]; - cldvst_dev(i) = cldvst[i]; - rain_dev(i) = rain[i]; - } + cldst_arr, evapr_arr, prain_arr, cldv_dev, + cldvcu_dev, cldvst_dev, rain_dev); }); // Create mirror views for output arrays